[英]Reliable way to determine variable message length when receiving from socket
I have some Python code for capturing images from a camera and sending them to a C# server. 我有一些Python代码,用于从相机捕获图像并将其发送到C#服务器。
When sending the messages from the client- I precede the data with the message size so I know how much data to pull from the socket server-side. 从客户端发送消息时,我会在数据之前加上消息大小,这样我就知道要从套接字服务器端提取多少数据。
It seems to work well most of the time, but occasionally - the message doesn't appear to start with the message size. 在大多数情况下,它似乎运行良好,但有时-消息似乎并非以消息大小开头。
I'm not sure why this is happening but I can't figure out how to deal with it. 我不确定为什么会这样,但是我不知道如何处理。
Python code: 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# C#
private const int MESSAGE_CHUNK_SIZE = 4096;
private const int MESSAGE_PREFIX_SIZE = 4;
private void _receiveMessage(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
List<byte> messageBuffer = new List<byte>();
byte[] tempBuffer = new byte[MESSAGE_CHUNK_SIZE];
try
{
handler.EndReceive(ar);
messageBuffer.AddRange(state.messageBuffer);
while (true)
{
while (messageBuffer.Count < MESSAGE_PREFIX_SIZE)
{
handler.Receive(tempBuffer, 0, MESSAGE_CHUNK_SIZE, 0);
messageBuffer.AddRange(tempBuffer);
}
int messageLength = _getMessageLength(messageBuffer);
// Occasionally the four bytes determining message length
// are read from what appears to be mid message
if (messageLength > 20)
{
Console.Write("halp");
}
messageBuffer = messageBuffer.Skip(MESSAGE_PREFIX_SIZE).ToList();
while (messageBuffer.Count < messageLength)
{
handler.Receive(tempBuffer, 0, StateObject.messageChunkSize, 0);
messageBuffer.AddRange(tempBuffer);
}
var wholeMessage = messageBuffer.Take(messageLength).ToList();
var messageString = Encoding.Default.GetString(wholeMessage.ToArray());
Console.WriteLine(messageString);
messageBuffer = messageBuffer.Skip(messageLength).ToList();
}
}
catch (SocketException ex)
{
Console.WriteLine(ex.Message);
}
}
private int _getMessageLength(List<byte> message)
{
byte[] bytes = { message[3], message[2], message[1], message[0] };
return BitConverter.ToInt32(bytes, 0);
}
The message buffer should look something like this: 消息缓冲区应如下所示:
On a good run: 在良好的运行中:
On a bad run: 在糟糕的情况下:
The problem appears to be with this code: 问题似乎与以下代码有关:
handler.Receive(tempBuffer, 0, StateObject.messageChunkSize, 0);
messageBuffer.AddRange(tempBuffer);
Socket.Receive()
returns the number of bytes actually read into the tempBuffer
. Socket.Receive()
返回实际读入tempBuffer
的字节数。 You need to save that value, and then use it to copy the correct number of bytes to messageBuffer
. 您需要保存该值,然后使用它将正确的字节数复制到messageBuffer
。
int bytesRead = handler.Receive(tempBuffer, 0, StateObject.messageChunkSize, 0);
messageBuffer.AddRange(tempBuffer.Take(bytesRead));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.