C# 从套接字接收时确定可变消息长度的可靠方法

C# 从套接字接收时确定可变消息长度的可靠方法,c#,.net,sockets,tcp,C#,.net,Sockets,Tcp,我有一些Python代码,用于从照相机捕获图像并将其发送到C#server 当从客户端发送消息时,我在数据前面加上消息大小,以便知道从套接字服务器端提取多少数据 在大多数情况下,它似乎工作得很好,但偶尔—消息似乎不是以消息大小开始的 我不知道为什么会发生这种情况,但我不知道如何应对 Python代码: while True: send_message("SEND_FRAME_DATA_HERE") def send_message(message): message_size

我有一些Python代码,用于从照相机捕获图像并将其发送到C#server

当从客户端发送消息时,我在数据前面加上消息大小,以便知道从套接字服务器端提取多少数据

在大多数情况下,它似乎工作得很好,但偶尔—消息似乎不是以消息大小开始的

我不知道为什么会发生这种情况,但我不知道如何应对

Python代码:

while True:
    send_message("SEND_FRAME_DATA_HERE")

def send_message(message):

    message_size = len(message.encode())

    print (f"Message: {message_size} - {message}")

    my_socket.sendall(struct.pack(">L", message_size) + message.encode())
C#

private const int MESSAGE\u CHUNK\u SIZE=4096;
private const int MESSAGE_PREFIX_SIZE=4;
private void\u receiveMessage(IAsyncResult ar)
{
StateObject状态=(StateObject)ar.AsyncState;
套接字处理程序=state.workSocket;
List messageBuffer=新列表();
字节[]临时缓冲区=新字节[消息块大小];
尝试
{
handler.EndReceive(ar);
messageBuffer.AddRange(state.messageBuffer);
while(true)
{
while(messageBuffer.Count<消息前缀大小)
{
接收(tempBuffer,0,消息块大小,0);
messageBuffer.AddRange(tempBuffer);
}
int messageLength=_getMessageLength(messageBuffer);
//有时,四个字节决定消息长度
//从似乎是中间消息的内容中读取
如果(messageLength>20)
{
控制台。写入(“halp”);
}
messageBuffer=messageBuffer.Skip(MESSAGE_PREFIX_SIZE).ToList();
while(messageBuffer.Count
消息缓冲区应如下所示:

运行良好时:

跑得不好时:


问题似乎与此代码有关:

handler.Receive(tempBuffer, 0, StateObject.messageChunkSize, 0);
messageBuffer.AddRange(tempBuffer);
Socket.Receive()
返回实际读入
tempBuffer
的字节数。您需要保存该值,然后使用它将正确的字节数复制到
messageBuffer

int bytesRead = handler.Receive(tempBuffer, 0, StateObject.messageChunkSize, 0);
messageBuffer.AddRange(tempBuffer.Take(bytesRead));

问题是您发送的邮件大小错误,或者您没有从以前的邮件中提取所有邮件。TCP有一个keep-alive,它是一个零字节的数据报。所以忽略长度为零的消息。此外,您的字节计数必须始终为相同的字节数。因此,如果您的大小为0 65535(2个字节),请不要发送一个字节作为大小。您收到的代码必须始终以两个字节作为大小。客户端只是一遍又一遍地发送相同的字符串,所以我认为不可能是这样。。我不确定你所说的字节数到底是什么意思,一定是同一个数字?无论消息大小如何,大小始终应为整个消息的前四个字节。。消息的长度可以是可变的
int bytesRead = handler.Receive(tempBuffer, 0, StateObject.messageChunkSize, 0);
messageBuffer.AddRange(tempBuffer.Take(bytesRead));