簡體   English   中英

NetworkStream.Length替代

[英]NetworkStream.Length substitute

我正在使用networkstream在網絡上傳遞短字符串。
現在,在接收方,我遇到了一個問題:
通常我會這樣閱讀

  1. 查看是否有數據
  2. 獲取可用數據計數
  3. 將那么多字節讀入緩沖區
  4. 將緩沖區內容轉換為字符串。

在假定所有提供的方法都可以正常工作的代碼中,看起來像這樣:

NetworkStream stream = someTcpClient.GetStream();
while(!stream.DataAvailable)
    ;

byte[] bufferByte;
stream.Read(bufferByte, 0, stream.Lenght);
AsciiEncoding enc = new AsciiEncoding();
string result = enc.GetString(bufferByte);

但是,MSDN表示NetworkStream.Length並未真正實現,並且在調用時始終會引發Exception。
由於傳入的數據長度不同,因此我無法對期望的字節數進行硬編碼(這也是幻數反模式的情況)。

題:
如果無法准確獲取可供讀取的字節數,那么如何正確地從流中讀取數據,而又不會冒NetworkStream.Read中的各種異常的風險?

編輯
盡管提供的答案可以帶來更好的總體代碼,但我仍然想分享我遇到的另一個選擇:
TCPClient.Available給出可讀取的字節。 我知道必須有一種方法來計算自己收件箱中的字節數。

不能保證連接一側的Read調用與另一側的Write匹配1-1。 如果你處理的可變長度的消息,它給提供接收方使用此信息。

一種常見的方法是首先確定您要發送的消息的長度,然后再發送該長度信息。 在接收端,您首先要獲得長度,然后知道要分配多大的緩沖區。 然后,您可以循環調用Read ,直到讀取了正確的字節數為止。 請注意,在您的原始代碼中,您當前忽略Read的返回值,該值告訴您實際讀取了多少字節。 在一次調用和返回中,即使您要求的字節數超過1個,該值也可能低至1。

另一種常見的方式是確定消息的“格式”-例如,消息號1的長度始終為32字節,並具有X結構,消息號2的長度為51字節,並具有Y結構。 使用這種方法,而不是在發送消息之前先發送消息長度 ,而是發送格式信息,而是先發送“這里是類型為1的消息”,然后再發送消息。

如果適用的話,另一種常見的方式是使用某種形式的哨兵-如果您的消息永遠不會包含值0xff的字節,則您掃描接收到的字節,直到收到0xff字節為止,然后0xff字節之前的所有內容。字節是您要接收的消息。

但是,無論你想做的事,其上面的方法之一,還是其他什么東西,是否它給讓你的發送和接收雙方共同努力,使接收器發現每條消息。


我忘了說,但是改變周圍一切的另一種方法是-如果您想交換消息 ,並且不想做以上任何擺弄,然后切換到更高級的東西-例如WCF或HTTP或其他方式,這些系統已經在處理消息幀,然后您可以專注於處理消息。

您可以使用StreamReader讀取流到底

var streamReader = new StreamReader(someTcpClient.GetStream(), Encoding.ASCII);

string result = streamReader.ReadToEnd();

暫無
暫無

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

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