gpt4 book ai didi

c++ - UDP 套接字是将接收到的数据划分为不同的消息,还是 recv 一次读取尽可能多的数据?

转载 作者:行者123 更新时间:2023-11-30 04:00:40 24 4
gpt4 key购买 nike

假设我有一个发送方应用程序和一个接收方应用程序,它们通过 UDP 进行通信。

首先,在发送方应用程序中,我在两个单独的调用中发送了一些数据。首先我发送这 15 个字节:

[MYHEADER]你好

...然后,紧接着,我又发送了 15 个字节:

[MYHEADER]世界

现在,在接收器应用程序中,我正在使用绑定(bind)到同一地址的 UDP 套接字在同一端口上监听。假设自从我上次检查接收器套接字以来,两条消息都已到达(并且顺序相同)。

下面是一些伪代码,展示了我如何轮询套接字以获取每帧的传入数据:

uint32 PendingSize;
while (Socket->HasPendingData(PendingSize))
{
uint32 BytesRead;
uint8 MessageData[kMaxMessageSize];

if (Socket->Recv(MessageData, kMaxMessageSize, BytesRead))
{
// Do stuff here
// Will BytesRead be equal to PendingSize?
}
}

HasPendingData 使用 FIONREAD 包装对 ioctlsocket 的调用,返回数据是否在接收缓冲区中等待,并填充 PendingSize 等待的字节数。 Recv 调用 recv 将该数据读入我可以读取的缓冲区。如果它返回 true,那么我将响应我收到的数据。

这是我的问题。以下哪种情况准确地反射(reflect)了这种情况下会发生什么?

选项 A.

  1. HasPendingData 返回 true 并显示 15 字节的待定大小。 Recv 给我消息 [MYHEADER]hello
  2. HasPendingData 返回 true 并显示 15 字节的待定大小。 Recv 给我消息 [MYHEADER]world
  3. HasPendingData 返回 false。

选项 B。

  1. HasPendingData 返回 true 并显示 30 字节的待定大小。 Recv 给我消息 [MYHEADER]hello[MYHEADER]world
  2. HasPendingData 返回 false。

任何见解都值得赞赏。谢谢!

最佳答案

UDP 数据报是独立且自包含的。

send()sendto() 每次发送一个新的数据报。

recv()recvfrom() 读取一个完整的数据报。如果您的缓冲区太小而无法接收给定的数据报,您将收到一个 WSAEMSGSIZE 错误,并且如果您没有指定 MSG_PEEK 标志,该数据报将会丢失。

FIONREAD 告诉您套接字接收缓冲区中的原始字节总数,而不是数据报的数量或这些数据报的大小。 documentation 中明确说明了这一点:

FIONREAD
Use to determine the amount of data pending in the network's input buffer that can be read from socket s. The argp parameter points to an unsigned long value in which ioctlsocket stores the result. FIONREAD returns the amount of data that can be read in a single call to the recv function, which may not be the same as the total amount of data queued on the socket. If s is message oriented (for example, type SOCK_DGRAM), FIONREAD still returns the amount of pending data in the network buffer, however, the amount that can actually be read in a single call to the recv function is limited to the data size written in the send or sendto function call.

如果您需要检查下一个数据报的大小,请使用 MSG_PEEK 标志调用 recv()recvfrom()。一旦确定了数据报的实际大小,就可以在没有标志的情况下读取它,以便将其从套接字缓冲区中删除。否则,只需分配一个足够大的缓冲区来容纳您将接收到的最大数据报,或者甚至只是 65535,这是 UDP 支持的最大大小。

因此,为了回答您的问题,您的示例中真正发生的是选项 A,除了第一个 HasPendingData 将报告 30 个待处理字节而不是 15 个字节。

关于c++ - UDP 套接字是将接收到的数据划分为不同的消息,还是 recv 一次读取尽可能多的数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26184970/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com