读取UDP套接字两次,在第一次调用后丢弃剩余字节
Reading UDP socket twice discards remaining bytes after first call
我的目标是分两步从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()
呼叫时阻塞。根据手动:
调用将阻塞,直到下列条件之一为真:
∙提供的缓冲区已满。[…]
∙发生错误。
为什么缓冲区是空的?如果我启动
echo '0123456789' | nc -u localhost 1234
第二次, receive()
调用解除阻塞,但也输出01
。在哪里我第一次输入的剩余数据23456789
去了吗?我如何在后续访问它receive()
电话吗?
一些背景:这个用例正在读取一个可变长度的数据包,这意味着先读标题,然后再读头被处理(包括关于包长度的信息)继续读取有效负载
UDP是面向数据包的协议。您必须一次读取整个数据包。
技术术语是"消息边界保留"。这意味着它将在一个块中发送来自单个write
或send
操作的所有数据。当你read
或recv
时,它将从特定的块中获取数据,然后丢弃该块,永远不会再看到。
这是故意的。
你应该在你的协议中决定一个最大的数据包长度,然后总是读取这个长度。如果写入的字节数小于该长度,则读取的字节数将少于要求的字节数。
另外,请记住,在UDP中没有保证任何给定的块将到达。所以如果两边都算的话,读的次数可能不如写的次数多。
像这样:
#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;
}
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 在UNIX系统中使用DIR查找文件的字节大小
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- std::当在256字节边界上写入整数时,流的奇怪行为
- 当比特(而不是字节)的顺序至关重要时的持久性
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何在文件中查找字节序列
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 字节到位运算符重载C++
- 在java中读取c++字节的位字段
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 字节真的是最小可寻址单元吗
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- 如何使用 OpenCV 解码在两个 UWP 应用之间发送的图像字节?
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- asn1c 不会从 asn.1 模块中提取八位字节字符串的默认值
- 找到一种有效的方法,在 2 个巨大的缓冲区上执行 MAX,每字节字节
- 联合类型定义中的冗余字节