簡體   English   中英

NetworkStream.DataAvailable更新緩慢

[英]NetworkStream.DataAvailable slow to update

我正在編寫一個基本的TCP / IP服務器以接收來自現有客戶端的消息。 目前,我能夠接收單緩沖區消息和多緩沖區消息。 當客戶端發送一組多條消息時出現問題。 它期望將流打開,並且將流中的所有消息在流再次關閉之前一個接一個地發送,而不是作為單個通信發送每個消息。 我已經在下面的編輯代碼段中對此進行了編碼:

private void AcceptMessage(IAsyncResult ar)
{
    String receivedMessage = "";

    //  Only run if the server is listening. Otherwise, an exception will be thrown.
    if (isListening)
    {
       ASCIIEncoding encoder = new ASCIIEncoding();
       try
       {
           TcpListener listener = (TcpListener)ar.AsyncState;
           using (TcpClient client = listener.EndAcceptTcpClient(ar))
           using (NetworkStream stream = client.GetStream())
           {
               int bytesRead;
               int totalBytes = 0;
               stream.ReadTimeout = ReadTimeout;
               do
               {
                   byte[] receivedBytes = new byte[BufferSize];
                   StringBuilder message = new StringBuilder();
                   bytesRead = 0;
                   do
                   {
                       try
                       {
                           if (stream.CanRead)
                           bytesRead = stream.Read(receivedBytes, 0, BufferSize);
                       }
                       catch (...Exception Handling...)

                       if (bytesRead == 0)
                           break;

                       message.Append(encoder.GetString(receivedBytes, 0, bytesRead));
                       totalBytes += bytesRead;
                   } while (bytesRead == BufferSize);     //  Allow for multiple buffers in a single message
                   byte[] ack = encoder.GetBytes(GetAck(message.ToString(), ackNak, status, statusMessage));
                   stream.Write(ack, 0, ack.Length);
                   ...Message Processing...
               } while (stream.DataAvailable);         //  Allow for multiple messages                        
           }
       }
       catch (...Error Handling...)
       finally { ...Cleanup...}
   }
}

問題出在第二while (stream.DataAvailable); 進行檢查時,在發送一組消息時,DataAvailable顯示為false,但是如果我在下一行放置一個中斷,它將顯示為true。 換句話說,它正在檢查數據是否可用。 我可以通過在檢查是否有更多消息之前增加一秒鍾的延遲來解決此問題,但是在100個案例中有99個案例中,這將是不必要的延遲。 由於客戶端一次只能發送一個消息(或一組消息),因此在繁忙時間可能會增加大量時間來接收消息。

有沒有更好的方法來確定是否還有更多待處理的消息(無需客戶端修改)? 謝謝!

編輯

我更改了代碼以包含建議。 我添加了一個暫停,並改變了第一次檢查,從stream.DataAvailablebytesRead == BufferSize 我無權訪問客戶端軟件,因此無法添加EOM傳輸。 我也不保證會在單個流中還是在多個單獨的流中發送多個消息。 我仍然沒有弄清楚如何判斷是否還有更多待處理的消息。 我無法將流保持打開狀態,因為這會阻止下一次傳輸。

我將Elgonzo標記為答案,因為他在我的問題的大部分方面都提供了幫助。 它仍然沒有回答如何判斷是否有待處理的消息,這可能是不可能的,但是我的經理決定,一旦連接打開,我們就應該將其作為專用連接保持打開狀態。 之所以可行,是因為我們的偵聽器僅通過內部安全網絡以一致的流量與單個設備通信。 如果在一定時間內沒有任何活動,我們將添加超時以斷開連接。

數據是否可用以及在服務器端傳入的數據的速度(和周期性)不僅取決於客戶端的時間/行為,還取決於它們之間的網絡/互聯網連接的速度和延遲因素(這本身取決於許多未知因素)。

結果,您將無法在外部while循環中使用stream.DataAvailable來檢查是否還會有其他數據。 您可能必須在NetworkStream上設置ReadTimeout才能知道客戶端何時完成/斷開連接。

同樣,最好在客戶端將要結束其連接時實現特定的信號/消息,以由客戶端發送,並且不僅依賴於超時。 這將幫助您解決問題(原因不明確是服務器還是客戶端中的錯誤,還是問題是由網絡連接問題引起的)的故障排除。

該問題的答案中的實現細節(盡管在不同的應用場景中,方法是相同的): 從封閉的NetworkStream讀取不會引起任何異常

此外,即使您的內部while循環也可能在糟糕的/緩慢的網絡連接上失敗,並且可能使您收到來自客戶端的部分接收到的消息,只是因為stream.DataAvailable在下一個數據包之前可能會為假(繼續當前消息)將被接收...

我建議啟動自己的線程,該線程在后台運行,如果有可用數據,則僅從流中讀取數據。 如果接收到數據,則只需收集數據,直到收到完整的消息(應由定義的字節或字節序列指示),然后觸發一個事件。 我認為這應該有助於避免該問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM