簡體   English   中英

NetworkStream正在讀取不應存在的數據

[英]NetworkStream is reading data that should not be there

NetworkStream從套接字緩沖區讀取不應存在的數據時遇到問題。 順便說一下,我正在發送很大的緩沖區。 現在,我剛剛在本地主機上進行測試。

這是我讀取數據的方式,前4個字節包含消息的長度,然后我只讀取4096個塊,直到達到消息的長度。

    protected TcpClient tcpObject;
    protected NetworkStream tcpStream;

    private void HandleComm()
    {
        try
        {
            tcpStream = tcpObject.GetStream();
            byte[] totalByteAray = new byte[constIntSize];
            byte[] message = new byte[constChunkSize];
            byte[] fullMessage = new byte[0];

            //this is how many bytes long the message will be
            int totalBytes = 0;
            int currentBytes = 0;
            int chunkSize = constChunkSize;

            while (true)
            {
                //skip reading if no data is available
                //DataAvailable does not tell you when all the data has arrived
                //it just tell you if some data has arrived
                if (tcpStream.CanRead)
                {
                    totalBytes = 0;
                    currentBytes = 0;
                    message = new byte[constChunkSize];
                    chunkSize = constChunkSize;

                    //The first 4 bytes of the message will always contain the length of the message, not including
                    //the first 4 bytes. This is how you know when to stop reading.
                    tcpStream.Read(totalByteAray, 0, constIntSize);                        
                    //there are 4 bytes in a 32 bit number, so totalByteArrayContains 4 index that is a byte which is
                    //the 32 bit int that tells us how many bytes the whole message will be.
                    //now convert the totalByteArray to a 32bit int
                    totalBytes = BitConverter.ToInt32(totalByteAray, 0);
                    Console.WriteLine("reading " + totalBytes);
                    //fullMessage will contain the entire message but it has to be built message by message.                    
                    fullMessage = new byte[totalBytes];
                    //keep reading until we get all the data
                    while (currentBytes < totalBytes)
                    {

                        //when you send something over TCP it will some times get split up
                        //this is why you only read in chuncks, 4096 is a safe amount of bytes
                        //to split the data into.
                        if (totalBytes - currentBytes < constChunkSize)
                        {
                            chunkSize = totalBytes - currentBytes;
                            message = new byte[chunkSize];
                        }

                        tcpStream.Read(message, 0, chunkSize);
                        //since we know each chunk will always come in at 4096 bytes if it doesn't that means that it's the end
                        //this part cuts off the extra empty bytes                           

                        //copy the message to fullMessage starting at current bytes and ending with the bytes left
                        message.CopyTo(fullMessage, currentBytes);
                        currentBytes += chunkSize;                            
                    }

                    //message has successfully been received
                    if (totalBytes != 0)
                    {

                        if (OnRawDataReceived != null)
                        {
                            RawDataReceivedArgs args = new RawDataReceivedArgs();
                            args.Data = new byte[fullMessage.Length];
                            fullMessage.CopyTo(args.Data, 0);
                            OnRawDataReceived(this, args);
                        }

                        totalBytes = 0;
                    }
                }
            }
        }
        catch
        {
            connectionStatus = ConnectionStatus.NotConnected;
            if (OnDisConnect != null)
                OnDisConnect(this, null);
        }
    }

這是我發送數據的方式,我只獲取消息的長度,然后創建一條新消息,其中前4個字節為消息的長度,其余為實際消息。

    protected void sendData(byte[] data)
    {
        //we need to know how big the data that we are sending will be
        int length = data.Length;
        System.Console.WriteLine("writing " + length);
        //convert the 32bit int to a 4 byte array
        byte[] lengthArray = BitConverter.GetBytes(length);

        //init the main byte array that will be sent over
        byte[] buffer = new byte[length + constIntSize];

        //the first 4 bytes will contain the length of the data
        lengthArray.CopyTo(buffer, 0);

        //the rest of the buffer will contain the data being sent
        data.CopyTo(buffer, constIntSize);

        //wite it to the client stream
        tcpStream.Write(buffer, 0, length + constIntSize);
        //now send it
        tcpStream.Flush();           
    }

由於某種原因,我正在讀取數據,不應將其放在緩沖區中。 這是控制台輸出。

服務器-------------客戶端

寫1024->閱讀1024

閱讀1228800 <-寫1228800

寫1024->閱讀1024

閱讀1228800 <-寫1228800

閱讀7224842

因此,當我單擊一個按鈕時,它會發送一個請求,說我要從網絡攝像機獲取圖像,該請求為1024字節。 客戶端讀取它並發送1228800字節的圖像。 我第一次這樣做,總是可以的。 我第二次單擊它,客戶端發回了1228800個字節,服務器讀取了正確的字節數,然后在套接字緩沖區應該為空時發現了更多要讀取的字節。 我在套接字緩沖區中沒有7224842字節,這就是讀取的前4個字節所說的。

關於為什么緩沖區要在其中獲取額外數據的任何想法? 當我發送較小的消息時,一切似乎都正常,但這使我發瘋。

tcpStream.Read(totalByteAray, 0, constIntSize);
...
tcpStream.Read(message, 0, chunkSize);

這樣我們就有了整個問題。 要求您檢查退貨要求。 不能保證(對於基於網絡的IO來說,幾乎不可能)一次獲得整個緩沖區-數據包隨時間傳入,並且API將為您提供所能提供的 相反,您將獲得“一些”(結果> 0和<=計數)或“無”(結果<= 0)。

如果你想讀的正是如此多的數據,然后寫一個實用的方法:

static void ReadExact(Stream stream, byte[] buffer, int offset, int count)
{
    int read;
    while(count > 0 && (read = stream.Read(buffer, offset, count)) > 0) {
        offset += read;
        count -= read;
    }
    if(count != 0) throw new EndOfStreamException();
}

暫無
暫無

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

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