gpt4 book ai didi

c - recvfrom 用零填充缓冲区

转载 作者:太空宇宙 更新时间:2023-11-04 08:06:50 26 4
gpt4 key购买 nike

我正在尝试通过 udp 实现距离 vector 路由。我有以下结构:

struct cost_info { 
uint8_t id;
uint8_t pad;
uint16_t cost;
}__attribute__((__packed__));

struct advertisement_packet {
uint8_t type;
uint8_t version;
uint16_t num_updates;
struct cost_info data[];
}__attribute__((__packed__));

所以数据包是1字节类型,1字节版本,2字节更新计数,然后是4*更新计数字节的数据。我正在使用灵活的数组成员,这样我就可以做

sendto(fd, pkt, sizeof(struct advertisement_packet) + pkt->num_updates * sizeof(struct cost_info), 0, addr, sizeof(struct sockaddr_in));

然后将整个东西放在一个数据包中发送。需要发送一个数据包。我能够使用 wireshark 验证数据是否被正确发送。在接收端,我做了两次接收。第一个获取前 4 个字节,因此我可以知道预期有多少更新。然后我相应地调整我的接收器缓冲区的大小并接收 4*num_updates 字节。问题是第二次接收用零填充了我的缓冲区!如果我期望 12 个字节的数据,我得到 12 个字节的零。下次我从那个套接字读取时,我会按预期获得下一个数据包的开头。为什么会这样?

如果需要,这是我的接收代码。

recvfrom(i, pkt, sizeof(struct advertisement_packet),0,NULL,0);
//reallocate more space if the incoming data will need it
if (pkt->num_updates > pkt_cost_slots) {
pkt_cost_slots *= 2;
pkt = realloc(pkt,sizeof(struct advertisement_packet) + sizeof(struct cost_info) * pkt_cost_slots);
assert(pkt);
}
//receive data
recvfrom(i,pkt->data,pkt->num_updates * sizeof(struct cost_info),0,NULL,0);

最佳答案

您不能将一个数据报的接收分成两个 recv()/recvfrom() 调用。发送和接收以数据报为单位进行操作是面向数据报的套接字的基本性质。但是,您可以读取部分或全部数据报,而无需将其从接收队列中删除(即“查看”它)。 The specifications for recvfrom()这么说吧:

For message-based sockets, such as SOCK_RAW, SOCK_DGRAM, and SOCK_SEQPACKET, the entire message shall be read in a single operation. If a message is too long to fit in the supplied buffer, and MSG_PEEK is not set in the flags argument, the excess bytes shall be discarded.

因此,您可以通过在第一个 recvfrom() 调用中使用 MSG_PEEK 来实现您的目标,但请注意,然后您需要接收整个 第二次 recvfrom() 调用中的数据报,而不仅仅是您第一次没有读取的部分。

关于c - recvfrom 用零填充缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42318304/

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