gpt4 book ai didi

c++ - 两次读取 UDP 套接字会丢弃第一次调用后剩余的字节

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:25:25 25 4
gpt4 key购买 nike

我的目标是分两步从 UDP 套接字读取数据。问题是如果我向套接字写入的数据多于第一步读取的数据。结果是剩余数据消失。

我将我的代码缩减为以下片段:

#include <boost/asio/ip/udp.hpp>
using namespace boost::asio;

int main() {
io_service net_io;
ip::udp::socket net_sock( net_io, ip::udp::endpoint( ip::udp::v4(), 1234 ) );

uint8_t data[2];

net_sock.receive( buffer( data, 2 ) );
std::cout << data[0] << data[1] << std::endl;

net_sock.receive( buffer( data, 2 ) );
std::cout << data[0] << data[1] << std::endl;


net_sock.close();
return EXIT_SUCCESS;
}

当我向套接字写入数据时如下:

echo '0123456789' | nc -u localhost 1234

程序输出前两个字节 01 然后阻塞。相反,我期望输出:

01
23

但是,它会在第二次 receive() 调用时阻塞。根据 manual:

The call will block until one of the following conditions is true:

∙ The supplied buffers are full. […]
∙ An error occurred.

为什么缓冲区是空的?如果我启动

echo '0123456789' | nc -u localhost 1234

第二次,receive() 调用解锁,但也输出 01。在哪里我第一次输入的剩余数据 23456789 是否消失了,我如何在后续访问它receive() 调用?

一些背景:用例是读取一个可变长度的数据包,这意味着先读取标题,然后再读取处理 header (其中包括有关数据包长度的信息)继续阅读有效负载。

最佳答案

UDP 是一种面向数据包的协议(protocol)。您必须一次读取整个数据包。

这方面的技术术语是“消息边界保留”。这意味着它将在一个 block 中发送来自单个 writesend 操作的所有数据。当您readrecv 时,它会从特定 block 中获取数据,然后丢弃该 block ,再也不会出现。

这是设计使然。

您应该在您的协议(protocol)中确定最大数据包长度,然后始终读取该长度。如果写入的长度小于该长度,读取的字节数将少于要求的字节数。

此外,请记住,在 UDP 中不能保证任何给定的 block 都会到达。因此,如果您同时计数,您的读取次数可能不如写入次数多。

像这样:

#include <boost/asio/ip/udp.hpp>
using namespace boost::asio;

const unsigned int max_datagram_size = 65536;

int main() {
io_service net_io;
ip::udp::socket net_sock( net_io, ip::udp::endpoint( ip::udp::v4(), 1234 ) );

uint8_t data[max_datagram_size];

// I like declaring all values that I do not expect to change as const.
const int recved_size = net_sock.receive( buffer( data, max_datagram_size ) );
if (recved_size >= 0) {
std::cout << ::std::string(data, recved_size) << '\n';
} else {
std::cout << "There was some sort of error receiving data.\n";
}


net_sock.close();
return EXIT_SUCCESS;
}

关于c++ - 两次读取 UDP 套接字会丢弃第一次调用后剩余的字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15523849/

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