我使用TCP套接字在项目的两个组件之间进行通信(两者都在本地运行)。一个充当服务器,处理数据并向另一个发送消息,充当客户端。
从服务器发送时,我首先发送一个4字节长的标头,然后是消息:
public void SendMessage(string message) {
var binaryMessage = Encoding.UTF8.GetBytes(message);
var messageLength = binaryMessage.Length;
var messageLengthBytes = BitConverter.GetBytes(messageLength);
_tcpClient.Client.Send(messageLengthBytes);
var bytesSent = _tcpClient.Client.Send(binaryMessage);
if (bytesSent != messageLength) {
_log.Warn($"Incorrect byte count send ({bytesSent} instead of {messageLength}).");
}
}
在客户端,接收时,我读取4个字节以获取长度标头,然后读取4KB块直到完成:
private const int RecBufferSize = 4096;
private readonly byte[] _recBuffer = new byte[RecBufferSize];
private void HandleNextIncomingMessage(IAsyncResult ar) {
var bytesReceived = _tcp.Client.EndReceive(ar);
if (bytesReceived != 4) {
_log.Error("Could not figure out the size of the incoming message - forcing reconnect.");
Reconnect();
return;
}
var array = _recBuffer.Take(4).ToArray();
var messageSize = BitConverter.ToInt32(array, 0);
var messageBuffer = new byte[messageSize];
var totalBytesFedIntoMessageBuffer = 0;
while (totalBytesFedIntoMessageBuffer < messageSize) {
var bytesToRead = messageSize - totalBytesFedIntoMessageBuffer;
if (bytesToRead > RecBufferSize) {
bytesToRead = RecBufferSize;
}
var bytesRead = _tcp.Client.Receive(_recBuffer, bytesToRead, SocketFlags.None);
if (bytesRead != bytesToRead) {
_log.Error($"Did not read the correct number of bytes {bytesToRead} from the network - read {bytesRead} - forcing reconnect.");
Reconnect();
return;
}
Buffer.BlockCopy(_recBuffer, 0, messageBuffer, totalBytesFedIntoMessageBuffer, bytesRead);
totalBytesFedIntoMessageBuffer += bytesRead;
}
HandleMessage(Encoding.UTF8.GetString(messageBuffer));
}
大多数消息都很小(<1KB),并且从不出现任何问题,但有一条特殊消息带有大量数据,大小可能为100-200KB。大多数情况下它是发送和接收没有问题,但偶尔一个块不包含正确的字节数,我看到日志行Did not read the correct number of bytes 4096 from the network - read 3472 - forcing reconnect.
。
陌生的是,这个数字并不总是3472,但经常是。
我是否正确地认为如果我将数据发送到服务器端的套接字,然后在客户端调用Receive
,它应该阻塞直到它收到完整的4096字节?如果是这样,为什么它偶尔会收到较少的字节数?