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

Thi*_*uda 5 .net c# sockets testing

我有一个直接使用'System.Net.Sockets.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();
    }
Run Code Online (Sandbox Code Playgroud)

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

Rus*_*sty 0

测试此类软件是否有任何“正式”的良好实践?

我可以谈论这一点,但我确信这里有一些很好的信息在堆栈中或在野外。

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

为了简单地开始,编写一些测试和日志记录例程,在一个单独的盒子上运行它们,这会用大量的请求......包括无意义的请求来攻击服务器。在两者上运行log4net也会有帮助。正如已经提到的,可以通过某种代理来引入一些延迟......位于客户端和服务器之间的一个盒子。客户端指向代理,代理修改数据...延迟、更改数据包顺序等...发送到服务器...反向并重复。顺便说一句...我会避免使用 Thread.Sleep(...)。最好使用这样的东西:

lock (timelock) { Monitor.Wait(timelock, TimeoutInMilliseconds); }
Run Code Online (Sandbox Code Playgroud)

...Socket.Accept/Socket.Receive 的异步版本?我可以替换异步方法来在单独的线程中处理同步版本吗?

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

以下是 MSDN 套接字条目中的异步服务器套接字示例

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

  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);
        }
      }
    }
  }
Run Code Online (Sandbox Code Playgroud)

希望这有帮助。

PS 获取一份C# 4.0 简而言之......很好。