通过UDP winsock连接发送结构,结构的大小?

时间:2014-06-26 10:56:45

标签: c++ sockets struct udp

我会尽量保持这一点。 因此,我制作了一个网络界面,其本身将用于创建简单的视频游戏。我最初开始用TCP设计它,但我发现它太慢了所以我切换到了UDP。

我当前的想法是这样的:我想发送结构,其中每个结构对应于特定的消息。当然,我需要知道服务器或客户端收到它时的结构大小。我通过首先发送一个标准化的结构来解决这个问题,该结构包含下一个结构的类型,然后相应地处理它。所以我会在客户端和服务器之间有类似共享头文件的东西,如下所示:

enum data_type { PLAYER_MESSAGE, PLAYER_LOCATION};

struct enum_type {
int nClientID;
data_type data_identifier;
};

struct player_message {
char message[128];
};

struct player_location {
int x, y;
};

然后,在接收其他客户端发送的数据的函数中,我会做这样的事情:

enum_type enum_check;
recvfrom(socket, (char*)&enum_check, sizeof(enum_type), 0, (struct sockaddr*)&client, &client_length);

switch(enum_check.data_identifier)
{

    case: PLAYER_MESSAGE
    player_message temp_message;
    recvfrom(socket, (char*)&temp_message, sizeof(player_message), 0, (struct sockaddr*)&client, client_length);
    //Print message
    break;

    case: PLAYER_LOCATION
    player_location temp_location;
    recvfrom(socket, (char*)&temp_location, sizeof(player_location), 0, (struct sockaddr*)&client, &client_length);
    //move player
    break;
}

系统可以很好地处理所有类型的消息,并且在(某些)压力下表现得相当不错。问题当然是每个客户端都会使用相同的recvfrom来首先检查消息类型然后相应地处理它。简而言之,我不太相信这个系统,因为它做了太多的假设。它假设给出消息类型的接收始终跟随正确的消息。使用UDP,你永远无法保证这种情况,这让我感到难过。 (我也意识到使用这种方法的字节序和计算机体系结构的问题,但我现在只是支持这种情况。)

我认为快速简单的方法是只有一种类型的结构,包括客户端ID,如何使用其数据(枚举),大约10个数字的空间以及一些文本。这样我就不必做出假设,但当然会不断地发送大量不必要的数据(如果带宽不是真正的问题,这不会成为一个问题,但它似乎是一个非常愚蠢的解决方案)

这里有什么建议吗?我打算只使用像ENET这样的网络库(那么再次,我不会在尝试发送结构时遇到同样的问题吗?)但这似乎是一种失败。毕竟,我只是这样做才能学习。

3 个答案:

答案 0 :(得分:1)

你已经抓住UDP的好事有时会以任意方式重新排序消息。

您始终发送包含所有可能信息的相同结构的解决方案几乎是正确的:

为自己定义一条基本信息,例如:

struct msg_common{uint8_t sender, receiver; uint16_t message_id;};
// Take note that I used fixed-width types here!

并使所有特定消息以此开头,为每个消息保留公共前缀的非重叠范围。

您无法确认消息是否有效,这意味着:

  • 这是完整的,又名。 UDP数据包包含整个消息。
  • 现在应该处理,也就是说。之前没有必须先处理的消息。
    • 包括重建以前未确认消息所需的所有数据。
    • 或接受删除任意数量的邮件。
    • 或允许请求重新发送。
  • 它不会违反游戏的其他一些语义限制。

答案 1 :(得分:1)

为什么不使用结构的联合,其中第一个成员给出结构的类型,并且对于联合中的所有结构是通用的。您的快速简便方法并不遥远,因为如果您只拥有10个数字,那么数据包的标头无论如何都会主导您的带宽使用。你真的不希望一个数据包检查下一个类型 - 这就是在UDP中要求麻烦,不能保证数据包按照它们发送的顺序到达。

答案 2 :(得分:0)

  

我最初开始在TCP中设计它,但我发现它太慢了所以我切换到了UDP。

我建议你在得出这样的结论之前先阅读这篇文章:udp-vs-tcp-how-much-faster-is-it。在大多数情况下,TCP相当不错。我的基于TCP的服务器在入门级xeon i7上使用双网卡运行乒乓测试,并且延迟相当快,我每秒获得400K数据包。

你需要多快?