2010-07-09 83 views
5

我有一个使用“System.Net.Sockets.Socket”直接用于网络交际的一类,目前我用下面的两个接口上破Socket类依赖:如何正确模拟C#套接字服务器测试中的高延迟?

public interface ISocketListener 
    { 
     void Listen(int backlog); 

     ISocket Accept(); 

     void Bind(EndPoint endpoint);    
    } 

public interface ISocket 
    { 
     void Connect (EndPoint ep); 

     Stream CommunicationStream { get; } 

     void Close(); 

     void Close(int timeout); 

     void Shutdown(); 
    } 

在生产实施我只是将所有方法调用重定向到私有套接字对象。在测试环境中,我使用MemoryStream作为套接字之间的通信“管道”。 因为我在这个主题方面经验不多,所以在写测试的时候,我的脑海中出现了一些问题:在测试这种软件方面是否有任何'正式'的良好实践?在进行集成测试时,如何测试此服务器在多个连接/高延迟情况下的性能(更具体地说,如何模拟这些情况)?为什么有Socket.Accept/Socket.Receive的异步版本?我可以替换异步方法来处理单独线程中的同步版本吗?

回答

0

在测试这种软件时是否有任何'正式'的良好做法 ?

我可以说这个,但我确定这里有一些很好的信息在堆栈或在野外。

在做集成测试,如何 做我测试在多个连接这个 服务器的性能/高 延迟的情况下(更具体地说, 如何模拟这些情况)?

为了一个简单的开始,写一些测试和日志记录程序,在一个单独的盒子上运行它们,这个程序以一系列的请求摧毁了服务器......包括无意义的请求。在两者上运行log4net也会有所帮助。正如已经提到的,通过一种代理服务器,一个位于客户端和服务器之间的盒子,可以实现一些延迟。客户端指向代理,代理修改数据...延迟,更改数据包顺序等...发送到服务器...反向并重复。稍微放一边...我会避免Thread.Sleep(...)。最好使用这样的事情:

lock (timelock) { Monitor.Wait(timelock, TimeoutInMilliseconds); } 

...异步版本 Socket.Accept/Socket.Receive?我可以用 替代异步方法 处理它们的同步版本 单独的线程吗?

你有很多选择,异步方法,普通旧线程,线程池,TPL等。最好的选择是特定于应用程序。

这是来自sockets上的MSDN条目的Asynchronous Server Socket Example

幸运的是,O'Reilly的书:C# 4.0 in a Nutshell有一组优秀的TCP Server examples,涵盖了阻塞/非阻塞表现形式中的异步/线程方法。这里是一个例子....

public class Server 
    { 
    public void Serve(IPAddress address, int port) 
    { 

     TcpListener listener = new TcpListener(address, port); 
     listener.Start(); 
     while (true) 
     { 
     TcpClient c = listener.AcceptTcpClient(); 
     Task.Factory.StartNew(Accept, c); 
     } 
    } 

    void Accept(object clientObject) 
    { 
     using (TcpClient client = (TcpClient)clientObject) 
     { 
     using (NetworkStream n = client.GetStream()) 
     { 
      byte[] data = new byte[5000]; 

      int bytesRead = 0; int chunkSize = 1; 

      while (bytesRead < data.Length && chunkSize > 0) 
      { 
      bytesRead += 
       chunkSize = n.Read /// Read is blocking 
       (data, bytesRead, data.Length - bytesRead); 
      } 

      Array.Reverse(data); 
      n.Write    /// Write is blocking 
      (data, 0, data.Length); 
     } 
     } 
    } 
    } 

希望这是有帮助的。

P.S.获得C# 4.0 in a Nutshell的副本...很好。

+0

谢谢你的提示,我要去看看这本书。 我认为设置另一台机器只是为了做一些集成测试有点矫枉过正。我希望测试速度快,并通过按下按钮来运行它们。 – 2010-07-09 16:32:08

+0

你当然可以在同一个盒子里做测试..但是你会共享相同的网络堆栈。所以你的结果会有点偏差。这不是一个交易破坏者,你应该意识到可能的副作用......享受。 – Rusty 2010-07-09 17:01:09

1

我不熟悉套接字对象。但是,我已经做了一些关于测试的研究。它看起来像你在正确的轨道上。编写可以引用生产中使用的实际对象或测试对象的接口通常被认为是很好的做法。这种模式被称为“依赖注入”。

我不知道套接字是如何工作的,但是你可以做的测试目的是创建一个新的测试对象来代替你想测试的套接字。该测试对象可以简单地调用Thread.Sleep(x)在返回数据之前添加一些模拟延迟。

编辑:我还想指出,您必须非常小心地确定网络延迟发生在您的代码中的哪个位置,以便在注入人为延迟时将其添加到代码在现实世界中会出现的地方。

+0

你的意思是将一些二进制数据分成块并使用Thread.Sleep间隔发送每个块?这是一个可能的解决方案,但我不确定是否能够正确模拟高延迟,不过我可能会试一试。怎么处理多个并发连接?那将如何处理? – 2010-07-09 16:06:37

+0

我在说的是,既然你已经编写了你自己的界面,你应该能够编写一个测试对象来模拟延迟并在你的测试环境中使用它。我不能说如何模拟延迟的细节。 – 2010-07-09 17:28:54

1

您可以通过创建一个代理服务器来连接您的连接来模拟高延迟,那么您可以在重新发送数据时添加延迟。

+0

你的意思是一个嘲笑的代理服务器?你能举个例子吗? – 2010-07-09 16:07:22