2012-05-17 36 views
0

我有一個代碼(讓我們假設一個簡單的聊天應用程序),我使用帶有同步的Tcp。但由於Async方式雖然設置起來更加困難,但我決定改變從同步到異步的方式。但現在我正在面臨一些使用異步的問題。使用帶有異步的Tcp接收消息的問題

  1. 緩衝區大小:我知道我們需要考慮有限的字節大小以獲取來自對端的字節。我讀了很多文章,但我的問題沒有解決,我有一個非常簡單但毫無價值的方法來應對這種情況,在每封郵件的末尾添加一個字符;那麼接收者可以理解消息何時被完全接收。但我還有另一個問題阻止我進一步解決其他問題。

讓我用下面的代碼解釋我的問題:

public void Send(byte[] message, Socket connection) 
{ 
    connection.BeginSend(message, 
         0, 
         message.Length, 
         SocketFlags.None, 
         new AsyncCallback(OnSend), 
         connection); 
} 

和OnSend方法,我只是用connection.EndSend(結果)其中結果的IAsyncResult。但是當我然後像下面的代碼那樣調用Send方法兩次時,OnReceive回調將接收它們作爲單個消息。

Send(Encoding.Unicode.GetBytes("Hello")); 
Send(Encoding.Unicode.GetBytes("Bye")); 

我OnReceiveMethod將使用Console.WriteLine(消息);其中消息是從對等端接收到的字符串。並使用同步方式的輸出必須是

你好

再見

但在異步方式我接收它作爲一個消息不是兩個,因此被印刷

HelloBye

此致敬禮 Peyman Mortazavi

回答

2

通過同步呼叫,您可以保證在發送第二條消息之前第一條消息已完全發送。但是,對於異步方法,您只需將兩條消息添加到傳出隊列中,等待發送。如果你碰巧在正確的時間點擊它,它可能會將它們作爲兩個單獨的消息發送,但由於您將它們添加得如此之快,所以它們很可能會一起發送。如果您將TCP/IP套接字通信視爲單個正在進行的數據流,那麼您的狀況會好得多。您需要以可確定開始和結束位置的方式格式化消息。當您通過套接字接收數據時,您應該繼續將收到的消息添加到緩衝區,直到確定(基於數據的格式)您已收到完整消息。你不應該依靠從套接字讀取每一個單一的完整信息。你應該期望它可能只是一個部分消息,甚至是多個消息。

+0

對,現在我在發送方法等待10毫秒,這是一個很短的時間,但將解決問題。並以自定義的格式,我可以理解消息何時開始和結束。 – Peyman

4

我必須說我不完全同意簡單地切換到同步套接字來解決這個問題。一個更好的方法是使用Queue<string>(例如)在發送呼叫時放置消息的位置。

然後,您將您的異步套接字從此隊列中取出隊列,並在當前隊列完成發送時發送下一個隊列,直到隊列爲空。

然後,您可以選擇不再次調用BeginSend,直到隊列中再次出現消息。