所以我在通过C ++中的客户端 - 服务器程序发送和接收自定义数据包时遇到了一些麻烦。我已经使用TCP实现了类似的功能,但是在使用UDP时,我遇到了将所有内容转换为单个数据报的问题。
目前我的标题包含偶数个uint32_t字段。其中每个都按照网络顺序存储,如标题结构:
uint32_t x = htonl (int y);
...
我正在将报头与有效载荷组合在一起,如下所示:
typedef struct {
450Header header; // 512 bytes consisting of the unint32_t like above
char data[ BLOCKSIZE ]; // 3.5k
// Total Packet Size = 4k
} Packet;
标题部分将包含有关数据包的信息,我的问题是如何处理字符串和有效负载的字节顺序。理想情况下,我希望在文件名中添加一些字符串字段,如果我发送的文件大于数据包中的blocksize,我想将其拆分成多个数据包,我需要知道如何拆分文件,因此可以按正确的顺序解释接收端。
我已经成功地独立构建了一个标题(所有字段都按网络字节顺序排列),如果我将它们添加到标题中,是否还需要转换字符串的顺序?我假设如果我将字符串保持在设定的大小,我仍然可以为标题编写校验和函数。
如果从问题1中正确订购了所有内容,我是否需要在接收端将它们再次转换回主机订单?
我有一个mmap函数将文件加载到char缓冲区中,我可以简单地使用memcpy和增量偏移量这样一块一块地复制到数据包中的数据缓冲区吗?或者我是否还要担心有效载荷数据的网络顺序?
我是否需要对有效负载使用校验和?如果它不使用整个缓冲区并以奇数个字节结束,我该怎么办呢?
最终我希望标题包含序列号,这样我就可以在丢弃数据包时练习实现程序(即返回N),所以我最担心的是标准化从客户端发送所有内容的顺序,以便它可以在服务器端以正确的顺序解释。
答案 0 :(得分:5)
8位数据(包括8位整数,Ansi / UTF-8字符串等)不会受到字节顺序问题的影响,因此您可以按原样发送/接收它们。只需要处理字节排序的多字节数据(如16位/ 32位整数,16位UCS2 / UTF-16字符串等)。例如,整数应始终采用网络字节顺序,但UTF-16字符串可以自行决定使用UTF-16LE或UTF-16BE(尽管您应该使用UTF-8)。
如果必须将数据拆分为多个包,则需要在数据包标头中放入信息以指定数据包的顺序。 UDP不保证数据包的到达顺序与它们发送的顺序相同,甚至不保证数据包到达。因此,接收方需要收集数据包(根据需要请求丢失数据包),然后在处理数据之前对其进行相应的重新排序。
是的,您应始终在发送数据包之前将数据包转换为网络字节顺序,并在接收端处理数据包时将其转换回主机字节顺序。转换为网络字节顺序仅用于传输目的,以确保跨平台的格式一致。
校验和是确保每个数据包的数据完整性的好主意,但这不是必需的。你可以确定为任意长度的数据提供固定长度的校验和,有很多校验和算法支持它。