2010-07-09 27 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