簡體   English   中英

來自NetworkStream的Write()和Read()原始字節,某些字節的數據存在差異

[英]Write() and Read() raw bytes from NetworkStream, data is difference at some bytes

我已經寫了一些代碼,用於在發送之前使用大小為KNOWN的NetworkStream發送byte []數組,但是在某些位置發送的數據和接收的數據有所不同。

MAXSIZE是我要發送的數據的已知大小。

    public static void SendBytes(TcpClient clientSocket, byte[] outStream)
    {
        Debug.WriteLine("SendBytes() number of bytes: " + outStream.Length.ToString());

        NetworkStream serverStream = clientSocket.GetStream();

        serverStream.Write(outStream, 0, outStream.Length);
        //serverStream.Flush();
    }

    public static byte[] ReceiveBytes(TcpClient clientSocket, int MAX_SIZE)
    {
        Debug.WriteLine("[" + DateTime.Now.ToString("G") + "] - " + "ReceiveBytes() started.");

        NetworkStream networkStream = clientSocket.GetStream();

        byte[] bytesFrom = new byte[MAX_SIZE];
        clientSocket.ReceiveBufferSize = MAX_SIZE;

        networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);

        Debug.WriteLine("[" + DateTime.Now.ToString("G") + "] - " + "ReceiveBytes(), received number of raw bytes: " + bytesFrom.Length.ToString());

        return CommonUtils.SubArray(bytesFrom, 0, MAX_SIZE);
    }

如果發送數據(十六進制字節):a7 fc d0 51 0e 99 cf 0d 00,則接收到的數據為:a7 fc d0 51 0e 99 cf 0d 53

由於數據包的結構化,很可能您會看到垃圾。 TCP僅保證正確的字節將以正確的順序到達(或流失敗)-它沒有說明它們到達的 因此, 至關重要的是:

  1. Read捕獲返回值,並且僅處理任何塊中的那么多字節
  2. 執行您自己的成幀-即將流分批成消息,與片段的到達方式無關

如果您的消息始終是固定大小,則“ 2”將變為“緩沖數據,直到我至少有N個字節,然后以N個塊的形式處理數據,保留剩下的所有內容,然后恢復緩沖”。 但是在一般情況下,它可能是“緩沖,直到我看到一個前哨值,例如換行”,或者是“緩沖,直到我有一個完整的標頭,然后解析標頭以查看期望的數據量,然后緩沖直到我有那么多數據”。

有一些工具和實用程序可幫助簡化幀刪除和處理積壓工作-例如,使用新的“管道” API,它只是檢查管道並告訴管道您要消耗多少(而不是管道)的一種情況。為您提供了一切,並且您現在暫時無法拒絕數據)-但是對於大多數人來說,從Stream切換到“管道”是相當多的變化。

就您而言,您可以使用:

byte[] bytesFrom = new byte[MAX_SIZE];
int outstanding = MAX_SIZE, read, offset = 0;
while (outstanding > 0 && (read = networkStream.Read(bytesFrom, offset, outstanding)) > 0)
{
    offset += read;
    outstanding -= read;
}
if (outstanding != 0) throw new EndOfStreamException();

這將創建一個讀取循環,該讀取循環將完全填充bytesFrom ,否則將失敗並發生異常。

Stream.Read返回一個值,該值指示實際讀取了多少數據。 絕不保證與您要求的金額相同。 忽略此值會帶來危險。

如果您樂意為整個流分配內存,為什么不只復制到MemoryStream並從中獲取全部緩沖區呢? Stream.CopyToStream.CopyToAsync是很好的高級抽象,使此操作變得容易。

暫無
暫無

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

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