如何在 TCP/IP 中为消息长度添加前缀
我通过 TCP/IP 发送消息,需要在字符数组中添加消息长度前缀,然后发送。我该怎么做?
您还可以提供一个如何在另一端提取它的示例吗?如果可能的话,请解释一下。
我正在使用 C++ 和 Winsock。
编辑:
string writeBuffer = "Hello";
unsigned __int32 length = htonl(writeBuffer.length());
它没有返回正确的长度,而是返回一个非常大的数字。
对于接收部分,如果我使用 ntohl(),那么我也会得到一个很大的数字而不是正确的长度?为什么会这样呢?我收到这样的
bool Server::Receive(unsigned int socketIndex)
{
// Read data from the socket
if (receivingLength)
{
bytesReceived = recv(socketArray[socketIndex - WSA_WAIT_EVENT_0],
((char*)&messageLength) + bytesReceived, MESSAGE_LENGTH_SIZE - bytesReceived, 0);
if (bytesReceived == SOCKET_ERROR)
{
return false;
}
if (bytesReceived == MESSAGE_LENGTH_SIZE)
{
// If uncomment the following line,
// I won't get the correct length, but a large number
//messageLength = ntohl(messageLength);
receivingLength = false;
bytesReceived = 0;
bytesLeft = messageLength;
}
}
else
{
if (bytesLeft > BUFFER_SIZE)
{
return false;
}
bytesReceived = recv(socketArray[socketIndex - WSA_WAIT_EVENT_0],
&receiveBuffer[bytesReceived], bytesLeft, 0);
if (bytesReceived == SOCKET_ERROR)
{
return false;
}
if (bytesReceived == messageLength)
{
// we have received full message
messageReceived = true;
receiveBuffer[bytesReceived] = '\0';
// wait for next message
receivingLength = true;
}
bytesLeft -= bytesReceived;
}
return true;
}
I'm sending messages over TCP/IP, I need to prefix message length in a char array and then send it. How do I do it?
Also can you please provide an example of how to extract it at the another end. And if possible, please explain.
I'm using C++ and Winsock.
EDIT:
string writeBuffer = "Hello";
unsigned __int32 length = htonl(writeBuffer.length());
It's not returning the correct length rather a very large number.
For the receiving part, if I use ntohl(), then I also get a large number instead of the correct length? Why is that so? I'm receiving like this
bool Server::Receive(unsigned int socketIndex)
{
// Read data from the socket
if (receivingLength)
{
bytesReceived = recv(socketArray[socketIndex - WSA_WAIT_EVENT_0],
((char*)&messageLength) + bytesReceived, MESSAGE_LENGTH_SIZE - bytesReceived, 0);
if (bytesReceived == SOCKET_ERROR)
{
return false;
}
if (bytesReceived == MESSAGE_LENGTH_SIZE)
{
// If uncomment the following line,
// I won't get the correct length, but a large number
//messageLength = ntohl(messageLength);
receivingLength = false;
bytesReceived = 0;
bytesLeft = messageLength;
}
}
else
{
if (bytesLeft > BUFFER_SIZE)
{
return false;
}
bytesReceived = recv(socketArray[socketIndex - WSA_WAIT_EVENT_0],
&receiveBuffer[bytesReceived], bytesLeft, 0);
if (bytesReceived == SOCKET_ERROR)
{
return false;
}
if (bytesReceived == messageLength)
{
// we have received full message
messageReceived = true;
receiveBuffer[bytesReceived] = '\0';
// wait for next message
receivingLength = true;
}
bytesLeft -= bytesReceived;
}
return true;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 TCP 流上发送长度字段时,您需要决定两件事:
我建议使用 4 字节长度,以及网络字节顺序(即大端字节序)。对于网络字节顺序,宏 htonl 和 ntohl 将在主机(本机)字节顺序(在您的情况下为小端)和网络字节顺序之间进行转换。
要发送数据,片段应如下所示:
在接收端,首先提取长度,然后提取数据:
此代码缺少的是错误处理:每个发送和接收调用都可能失败; recvs 接收到的数据可能比预期少。但这应该给你一个想法。
编辑:要处理recv返回的数据太少的情况,请在循环中运行它,记录到目前为止已读取的内容,例如
When sending a length field on a TCP stream, you need to decide two things:
I recommend to use 4 bytes length, and network byte order (i.e. big-endian). For network byte order, the macros htonl and ntohl will convert between host (native) byte order (little-endian, in your case), and network byte order.
To send data, the fragment should look like this:
On the receiving side, you extract first the length, then the data:
What this code is missing is error handling: each of the send and receive calls may fail; the recvs may receive less data than expected. But this should give you an idea.
Edit: To deal with the case that the recv returns too few data, run it in a loop, keeping a count of what you have read so far, e.g.
伪代码(错误处理省略,小心):
发送者:
接收者:
Pseudocode (error handling omitted, be careful):
sender:
receiver:
我不确定这是否是您所要求的,但我会将其作为固定长度的字符串发送(假设为 4 个字符,实际长度由您决定)。也就是说,如果数据长度为164,则发送字符串“0164”。这克服了另一端的任何字节顺序问题,并且易于阅读和调试。
要生成这样的字符串,您可以使用字符串流:
发送:
要在另一端读取它,如下所示:
I'm not sure if this is what you are asking, but I would send it as a string of a fixed length (let's say 4 characters, actual length up to you). In other words, if the data length is 164, send the string "0164". This gets over any problems of byte order at the other end, and is easy to read and debug.
To produce such strings, you can use a stringstream:
To send:
To read it at the other end, something like: