2016-10-27 70 views
0

我試圖確定可讀取的字節數,因此我可以從SslStream中讀取,直到讀取完所有數據。 SslStream似乎沒有屬性或方法來做到這一點,所以我一直在嘗試使用底層Socket。這裏的問題是由Socket報告的可用字節數與我需要的實際解密數據量不匹配。無法獲取SslStream的可用字節數

這是我的Receive方法:

byte[] Receive() 
{ 
    byte[] messageBuffer = new byte[4096]; 
    int bytesRead = 0; 

    using (var readData = new MemoryStream()) 
    { 
     while(Client.Client.Available > 0) 
     { 
      bytesRead = Stream.Read(messageBuffer, 0, messageBuffer.Length); 
      readData.Write(messageBuffer, 0, bytesRead); 
     } 

     return readData.ToArray(); 
    } 
} 

Client.ClientStream底層Socket這是SslStream。假設消息大小爲5000字節。這裏有幾個問題:

  1. 第一次嘗試閱讀Client.Client.Available返回5077.這不是正確的可用數據長度。
  2. 第一次撥打Stream.Read後Client.Client.Available返回0,所以我退出循環,即使我只讀了4096,因爲這是我的緩衝區大小。因此,流中還有904個字節沒有被讀取。

這樣看來,我稱之爲Stream.Read後其從插座中刪除全部數據(全部5000個字節不只是4096我所要求的),這是有道理的,因爲你需要整個消息進行解密。但是沒有辦法知道你是否已經收到全部信息,因爲沒有SslStream.Available或其他類似的東西。所以我的問題是如何知道我是否收到了整個解密的消息? (或者我怎樣才能得到解密的消息的字節數?)我已經試過

其他的事情:使用Client.Client.Poll(someLongTimeoutForTesting, SelectMode.SelectRead)

  • 但它首先Stream.Read後返回false也是如此。
  • 使用Client.GetStream().DataAvailable再次返回假後的第一個Stream.Read
  • 增加messageBuffer的大小來最大金額Stream.Read將返回(16299,不知道爲什麼這個號碼,但是當我增加了郵件大小和緩衝區超過這個大小Stream.Read()總是返回16299)。這種方法可以工作,但是它使用不合理的內存量,因爲在應用程序中它將用於客戶端消息的時間低於4096 99.99%。

回答

0

如果你知道消息的長度,可以讀取的字節數組,然後從這個數組創建流:

buffer = new byte[num_of_bytes]; 
    for (int i = 0; i < num_of_bytes; i++) 
     buffer[i] = (byte)sslStream.ReadByte(); 

    using (var stream = new MemoryStream(buffer)) 
    {     
    } 
+0

我不知道消息的長度,這正是我想要確定的。我剛剛在我的例子中使用5000來演示我的問題 – CSCoder

0

當您使用TCP套接字(流)工作,你需要實現自己的應用程序層協議。一個非常簡單的解決方案:在前兩個字節中指定消息大小(例如,它可以是您決定的長度),也可以爲消息類型分配一個或兩個字節(例如),其餘爲有效負載。所以,你知道前兩個字節總是表示長度,所以你必須讀2字節。然後你得到有效載荷長度。那時你知道有多少個字節需要讀取。我用更多細節解釋它,不是針對SslStream,但是對於您的情況,這個響應也是有效的,在這裏:How to read all of Inputstream in Server Socket JAVA

+0

感謝您的答案!這將是一個很好的解決方案,然而,不幸的是,這不是我的選擇,因爲我無法更新客戶端代碼。我可以驗證我收到的消息與預期的格式匹配,所以我可以接收不良/不完整的消息,但我的問題是,當消息超過messageBuffer大小時,我從來沒有收到正確/完整的消息。 – CSCoder