Bec*_*ker 1 c++ sockets network-programming packet
我有一个麻烦,我的服务器应用程序发送8字节长度的数据包 - AABBCC1122334455但我的应用程序分两部分收到此数据包,AABBCC1122并334455通过"recv"函数,我该如何解决?
谢谢!
总结一下liitle位:
send并recv可以发送和接收比参数提供的数据较少.你必须正确处理它(通常通过在呼叫周围应用适当的循环).从你已经提到的内容来看,你很可能想要发送某种消息(嗯,这通常是人们所做的).关键是要正确发现消息的边界.如果您的邮件大小固定,您只需从流中获取相同数量的数据并将其转换为您的邮件; 否则,你需要一个不同的方法:
如果你能想出一个在你的信息中不存在的角色,它可能是你的分隔符.然后,您可以阅读流,直到您到达角色,这将是您的消息.如果传输ASCII字符(字符串),则可以使用零作为分隔符.
如果您传输二进制数据(原始整数等),所有字符都可以出现在您的消息中,因此没有任何字符可以作为分隔符.在这种情况下,最常见的方法可能是使用包含邮件大小的固定大小的前缀.这个额外字段的大小取决于消息的最大大小(4个字节可能是安全的,但如果你知道最大大小是多少,你可以使用较低的值).然后您的数据包看起来像SSSS|PPPPPPPPP...(字节流),其中S是附加大小字段,P是您的有效负载(应用程序中的真实消息,P字节数由值确定S).您知道每个数据包都以4个特殊字节(S字节)开头,因此您可以将它们作为32位整数读取.一旦知道封装消息的大小,就可以读取所有P字节.完成一个数据包后,您就可以从套接字中读取另一个数据包了.
不过好消息,你可以想出一些完全不同的东西.您需要知道的是如何从字节流和方式send/ recv行为中反序列化您的消息.祝好运!
编辑:
将任意字节数接收到数组中的函数示例:
bool recv_full(int sock, char *buffer, size_t size)
{
size_t received = 0;
while (received < size)
{
ssize_t r = recv(sock, buffer + received, size - received, 0);
if (r <= 0) break;
received += r;
}
return received == size;
}
Run Code Online (Sandbox Code Playgroud)
并且接收具有定义有效载荷大小的2字节前缀的分组的示例(有效载荷的大小则限制为65kB):
uint16_t msgSize = 0;
char msg[0xffff];
if (recv_full(sock, reinterpret_cast<char *>(&msgSize), sizeof(msgSize)) &&
recv_full(sock, msg, msgSize))
{
// Got the message in msg array
}
else
{
// Something bad happened to the connection
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2100 次 |
| 最近记录: |