[英]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.