通过网络发送可变长度数组?

时间:2011-10-12 14:32:45

标签: c++ networking

在我正在制作的游戏中,我需要能够通过网络发送整数的std ::向量。

数据包似乎完全由字符串组成。由于enet,网络库我正在使用照顾endian,我解决这个的第一个想法是发送一个消息,其中第一个字节是消息id,像往常一样,接下来的4个字节将是一个整数,表示数组的长度,以及所有后续字节都是数组中的int。在客户端,我可以将它们推回到矢量中。

这是通常的方式,还是我错过了一些关键的东西?有没有更好的方法呢?

由于

3 个答案:

答案 0 :(得分:2)

一般来说,解决这个问题有两种方法可以结合起来。一种是将数组的长度放在实际数组之前。另一个涉及包括一些框架,以标记您的消息的结束(或开始)。各有利弊。

在数组之前放置长度是最简单的。但是,如果应该存在长度与整数不匹配的错误,则无法检测到此错误或从中恢复。

使用成帧字节标记消息的结尾具有更强大的优点,并且能够以复杂性为代价从格式不正确的消息中恢复。复杂性在于,如果您的成帧字节出现在整数数组中,则必须转义字节(即前置和转义字符)。此外,从网络读取消息的代码变得有点复杂。

当然,这一切都假定您正在处理流而不是数据报。如果您的邮件已经明确打包,那么长度应该足够了。

答案 1 :(得分:1)

有两种方法可以在流上发送可变长度数据:在数据前加上长度,或者用分隔符后缀。

后缀可以具有理论上无限大小,但这意味着分隔符不得出现在数据中。此方法可用于字符串,并使用NUL('\0')字符作为分隔符。

在处理二进制数据时,除了为长度加前缀外,你别无选择。数据的大小将限制为前缀的大小,这很少是4字节前缀的问题(因为否则它意味着您发送超过4千兆字节的数据)。

所以,这一切都取决于发送的数据。

答案 2 :(得分:0)

将标题信息附加到数据包是一种很好的方法。如果数据存储在内存的某个unsigned char*缓冲区中,您可以在接收端执行的另一个选项是创建如下结构:

typedef struct network_packet
{
    char id;
    int message_size;
    int data[];
} __attribute__((packed)) network_packet;

然后,您可以简单地将此结构“叠加”在接收缓冲区的顶部,如下所示:

unsigned char* buffer;
//...fill the buffer and make sure it's the right size -- endian is taken care of
//via library

network_packet* packet_ptr = (network_packet*)buffer;

//access the 10th integer in the packet if the packet_ptr->message_size
//is long enough
if (packet_ptr->message_size >= 10)
    int tenth_int = packet_ptr->data[9];

这将避免您不得不花费将已经存在于缓冲区中的所有数据复制回接收方的另一个std::vector