比使用c#套接字更短的预期接收

时间:2017-03-20 13:48:31

标签: c# sockets

我使用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字节?如果是这样,为什么它偶尔会收到较少的字节数?

0 个答案:

没有答案