2012-04-27 118 views
2

我寫了一個TCP服務器來使用BeginAccept/EndAccept模式。有了這個,我使用TcpClient編寫了一個簡單的UnitTest,並測量了每個部分。所有測試都是localhost,所以我很驚訝地看到TCP連接持續1秒。我已經設置了Socket.NoDelay = true,但我相信這隻會影響發送/接收。我沒有收到第一包數據。任何幫助或想法加快這一點讚賞。有什麼辦法可以改善TCP連接時間嗎?

注:我不能改變客戶端保持連接打開,我需要能夠處理大量的每秒如果可能的請求。

服務器端:

public void Start() 
{ 
    System.Net.IPHostEntry localhost = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()); 
    System.Net.IPEndPoint endpoint; 
    int port = Properties.Settings.Default.ListenPort; 

    // 
    // Setup the connection to listen on the first IP, and specified port 
    // 
    endpoint = new IPEndPoint(IPAddress.Any, port); 
    listenSocket = new Socket(endpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); 
    listenSocket.Bind(endpoint); 
    listenSocket.NoDelay = true; // do not wait 200 milliseconds for new data to be buffered on the connection 
    listenSocket.Listen(int.MaxValue); 
    Console.WriteLine("Listening on {0}:{1}", localhost.AddressList[0], port); 

    // 
    // Post the accept. The accept method will continuously post a new accept as soon as a connection is made 
    // 
    while (true) 
    { 
     accepted.Reset(); 
     Connection connection = connections.Pop(); 
     listenSocket.BeginAccept(AcceptCallback, connection); 
     accepted.WaitOne(); 
    } 
} 

private static void AcceptCallback(IAsyncResult ar) 
{ 
    accepted.Set(); 

    Connection connection = ar.AsyncState as Connection; 
    Socket remoteSocket = null; 

    try 
    { 
     remoteSocket = listenSocket.EndAccept(ar); 
     remoteSocket.NoDelay = true;     
     connection.RemoteSocket = remoteSocket; 

     // 
     // Start the Receive cycle 
     // 
     Receive(connection);    
    } 
    catch (SocketException) 
    { 
     Disconnect(connection); 
    }   
} 

簡單的測試客戶端:

[TestMethod()] 
public void ClientTest() 
{ 
    TestContext.BeginTimer("Connection"); 
    TcpClient client = new TcpClient("localhost", 10300); 
    NetworkStream stream = client.GetStream(); 
    TestContext.EndTimer("Connection"); 
    ... 

使用負載測試我裝25個用戶,而交易 「連接」 始終以超過1秒。

+1

嘗試使用嗅探Wireshark的,看看發生了什麼的TCP報文。 – Sjoerd 2012-04-27 06:55:13

+1

@esac:可能是主機名解析問題。是的,我看到主機名是「localhost」。但是你可以嘗試通過IP地址建立連接嗎? – Dennis 2012-04-27 07:09:44

+0

您是否正確釋放連接?您使用哪個操作系統作爲服務器?如果您運行的是Windows的非服務器版本,則很可能是由於連接限制而放慢速度。請參閱此[線程](http://stackoverflow.com/questions/657874/max-tcp-connections-to-a-machine)以獲取更多信息。 – 2012-04-27 10:39:38

回答

4

不知道爲什麼,但簡單地改變這樣的:

TestContext.BeginTimer("Connection");   
TcpClient client = new TcpClient("localhost", 10300);    
TestContext.EndTimer("Connection"); 

要這樣:

TestContext.BeginTimer("Connection"); 
TcpClient client = new TcpClient(); 
client.Connect("localhost", 10300);  
TestContext.EndTimer("Connection"); 

水滴從1秒到0.13秒的時間。將不得不調查爲什麼,但希望這將有助於未來的人。

+0

很抱歉喚醒了一個老問題,但我很好奇,如果您有任何解釋?這是真正的修復還是還有其他一些延遲原因? – jishi 2015-01-12 14:18:11

+0

@jishi見下面的la-comadreja評論 - 它解釋得很好。 – esac 2015-02-12 15:52:59

2

當您嘗試使用解析爲IPv6和IPv4地址的主機上的TcpClient構造進行連接,使用IPv6的連接首先嚐試。如果失敗,則嘗試使用Ipv6地址進行連接。這是1秒延遲的原因。 Here is the MSDN link

+0

這是一個答案? – 2012-09-29 00:39:20

+1

你重複了Ipv6,所以這真的是第一個? – 2014-07-02 13:36:10

+0

這個答案幫了我。我認爲,這種情況是比較容易理解從服務器端: 我結合我的服務器到IPv4環回,但隨後試圖通過域名連接「localhost」的到客戶端,從而解決雙方一個IPv6和IPv4地址。客戶端首先嚐試了IPv6地址,但由於服務器未在偵聽而失敗。它默認使用IPv4地址,但緩慢。我反而聽取了IPv6回送,並且它再次運行得很快。 – 2015-12-17 18:21:40

相關問題