2012-03-09 75 views
2

我正在從Android設備向C#中的TCP服務器發送傳感器數據。 Android客戶端以32字節的固定大小塊發送數據。TCP服務器沒有正確讀取固定大小的消息

在服務器中,我讀取的數據預計它會全包,但由於TCP是一個流協議,一些消息到達服務器分爲兩部分。我知道,因爲我可以用名爲SocketSniff的軟件來觀看它。

問題是我不知道如何在我的服務器上處理它。

我發現的所有例子都使用NetworkStream.Read(),在這個方法中我必須傳遞一個字節數組來存儲讀取的數據,偏移量和要讀取的字節數。這個字節數組必須有一個知道的大小,在我的情況下。32.

我不知道在我的服務器上到達的消息的實際大小,但它可能是以下情況之一。

  • 如果收到的數據大小是32字節,那一切都OK。

  • 如果收到的數據大小大於32字節,我認爲我丟失了數據。

  • 如果收到的數據大小小於32個字節,比如說20個字節,這些字節存儲在我的數組中,並且數組的最後12個字節保持零值。由於我可能確實收到了一些零,因此無法知道我真正收到的大小,所以我無法將它與剩餘的數據合併到下一個閱讀中。

我的代碼,處理接收如下:

int buffer = 32; 
    ... 
    private void HandleClientComm(object client) 
    { 
     TcpClient tcpClient = (TcpClient)client; 
     NetworkStream clientStream = tcpClient.GetStream(); 

     byte[] message = new byte[buffer]; 
     int bytesRead; 

     while (true) 
     { 
      bytesRead = 0; 

      try 
      { 
       bytesRead = clientStream.Read(message, 0, message.Length); 
      } 
      catch 
      { 
       break; 
      } 

      if (bytesRead == 0) 
      { 
       // Connection closed 
       break; 
      } 

      SensorData sensorData = ProcessTcpPacket(message); 
     } 
     tcpClient.Close(); 
    } 

有沒有辦法知道我收到插座上的數據的大小?

+1

不bytesRead不會返回你想要的大小? – 2012-03-09 20:04:06

+1

請不要用「C#」等標題來標題。這就是標籤的用途。 – 2012-03-09 20:05:21

+0

我問這個問題只是覺得很愚蠢。 BytesRead沒有返回正確數量的字節讀取,我不怎麼會錯過它... Thx – RBasniak 2012-03-09 20:47:14

回答

6

嗯,是的,你有bytesRead變量 - 它包含從流中讀取的字節數。你最多可以閱讀message.Length字節,但是你可能讀的更少。

請注意,如果有更多字節可用,您不會通過讀取message.Length字節而丟失它們。相反,下次您從流中讀取時,它們將可供您使用。

你需要做的是添加一個while循環喜歡這個:

int messageRead = 0; 

while(messageRead < message.Length) 
{ 
    int bytesRead = clientStream.Read(message, messageRead, message.Length - messageRead); 
    messageRead += bytesRead; 
    if(bytesRead==0) 
     return; // The socket was closed 
} 
// Here you have a full message 
+2

謝謝,分析bytesRead變量告訴我我失蹤了什麼,並且此代碼解決了所有問題以管理來自任何尺寸。 – RBasniak 2012-03-09 20:49:26