如何在C#socket服务器测试中正确模拟高延迟?

如何在C#socket服务器测试中正确模拟高延迟?,c#,.net,testing,sockets,C#,.net,Testing,Sockets,我有一个类直接使用“System.Net.Socket.Socket”进行网络通信,目前我使用以下两个接口来打破对Socket类的依赖: public interface ISocketListener { void Listen(int backlog); ISocket Accept(); void Bind(EndPoint endpoint); } public interface ISo

我有一个类直接使用“System.Net.Socket.Socket”进行网络通信,目前我使用以下两个接口来打破对Socket类的依赖:

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的异步版本?我可以在单独的线程中替换异步方法来处理它们的同步版本吗?

我不熟悉套接字对象。然而,我做了一些关于测试的研究。看来你走对了方向。编写可以引用将在生产中使用的实际对象或测试对象的接口通常被认为是良好的实践。这种模式被称为“依赖注入”

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


编辑:我还想指出,您必须非常小心地确定网络延迟在代码中的确切位置,以便在注入人工延迟时,您可以将其添加到代码中与实际情况相同的位置。

您可以通过在连接之间创建代理服务器来模拟高延迟,然后您可以在重新发送数据时添加延迟

是否有“正式”的良好实践 在测试这种软件时

我可以这么说,但我相信这里有一些很好的信息

在进行集成测试时,如何 我要测试这个的性能吗 服务器处于多个连接/高 延迟情况(更具体地说, 如何模拟这些情况

首先,编写一些测试和日志例程,在一个单独的框中运行它们,这些例程向服务器发出大量请求,包括一些无意义的请求。同时在这两个平台上运行也会有所帮助。如前所述,引入一些延迟可以通过一种代理来实现……一个位于客户机和服务器之间的盒子。客户端指向代理,代理修改数据…延迟、更改数据包顺序等…发送到服务器…反转并重复。顺便说一句……我会避免穿线。睡觉(…)。最好使用这样的方法:

lock (timelock) { Monitor.Wait(timelock, TimeoutInMilliseconds); }
…的异步版本 Socket.Accept/Socket.Receive?我可以吗 替换的异步方法 在中处理它们的同步版本 分开的线程

您有许多选项,异步方法、纯旧线程、线程池、等。最佳选择是特定于应用程序的

下面是上MSDN条目的一个示例

幸运的是,O'Reilly的书:有一套非常好的方法,涵盖了阻塞/非阻塞表现形式中的异步/线程方法。下面是一个例子

  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);
        }
      }
    }
  }
公共类服务器
{
公共无效服务(IP地址地址,int端口)
{
TcpListener侦听器=新的TcpListener(地址、端口);
listener.Start();
while(true)
{
TcpClient c=listener.AcceptTcpClient();
Task.Factory.StartNew(接受,c);
}
}
无效接受(对象clientObject)
{
使用(TcpClient客户端=(TcpClient)客户端对象)
{
使用(NetworkStream n=client.GetStream())
{
字节[]数据=新字节[5000];
int bytesRead=0;int chunkSize=1;
while(bytesRead0)
{
拜读+=
chunkSize=n.Read///Read正在阻塞
(数据,字节读取,数据.长度-字节读取);
}
数组。反向(数据);
n、 Write///Write正在阻塞
(数据,0,数据长度);
}
}
}
}
希望这是有帮助的


另外,获取…的副本很好。

您的意思是将一些二进制数据分割成块,并使用线程发送每个块。睡眠间隔?这是一个可能的解决方案,但我不确定这是否正确模拟了高延迟,我可能会尝试一下。处理多个并发连接怎么样?这将如何处理?我想说的是,既然您已经编写了自己的接口,那么您应该能够编写一个模拟延迟的测试对象,并在您的测试环境中使用它。我不能说延迟应该如何模拟的细节。你是说模拟的代理服务器?你能举个例子吗?谢谢你的提示,我要看看这本书。我认为仅仅为了做一些集成测试而设置另一台机器有点过分了。我希望测试速度快,并通过按下按钮来运行所有测试您当然可以从同一个框中进行测试..但是..然后您将共享同一个网络堆栈。所以你的结果会有点偏斜。这不是一个交易破坏者,你应该知道可能的副作用…享受。