【发布时间】:2019-06-07 05:09:16
【问题描述】:
我有一些 Python 代码用于从相机捕获图像并将它们发送到 C# 服务器。
从客户端发送消息时,我在数据前面加上消息大小,这样我就知道要从套接字服务器端提取多少数据。
它似乎在大多数情况下运行良好,但偶尔 - 消息似乎不是以消息大小开头的。
我不确定为什么会发生这种情况,但我不知道如何处理它。
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_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);
}
消息缓冲区应如下所示:
运行良好:
运行不佳:
【问题讨论】:
-
问题是您发送的大小错误,或者您没有从上一条消息中提取所有消息。 TCP有一个保持活动状态,它是一个零字节的数据报。所以忽略长度为零的消息。此外,您的字节数必须始终是相同的字节数。因此,如果您的大小为 0 65535(2 个字节),则不要发送一个字节作为大小。您收到的代码必须始终以两个字节为大小。
-
客户端只是一遍又一遍地发送相同的字符串,所以我认为不可能是这样。我不确定您所说的字节数必须始终是相同的数字是什么意思?无论消息的大小如何,大小都应始终是整个消息的前四个字节。并且消息的长度可以是可变的