Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 读取UDP套接字两次将丢弃第一次调用后剩余的字节_C++_Udp_Boost Asio - Fatal编程技术网

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

C++ 读取UDP套接字两次将丢弃第一次调用后剩余的字节,c++,udp,boost-asio,C++,Udp,Boost Asio,我的目标是分两步从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(), 123

我的目标是分两步从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;
}
程序输出前两个字节
01
,然后阻塞。 相反,我期望输出:

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

调用将被阻止,直到下列条件之一为真:

∙ 提供的缓冲区已满。[…]
∙ 发生了一个错误

为什么缓冲区是空的?如果我发射

echo '0123456789' | nc -u localhost 1234
第二次,
receive()。哪里
我第一次输入的剩余数据是否为23456789
数据,以及我如何在后续时间访问它
receive()
call

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

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;
}
#包括
使用名称空间boost::asio;
常量无符号整数最大数据报大小=65536;
int main(){
io_服务网络_io;
ip::udp::socket net_sock(net_io,ip::udp::endpoint(ip::udp::v4(),1234));
uint8_t数据[最大数据报大小];
//我喜欢将我不希望更改的所有值声明为const。
const int recved_size=net_sock.receive(缓冲区(数据,最大数据报大小));
如果(记录的大小>=0){

std::cout@Marco:在任何给定的写入操作中,至少读取尽可能多的字节。最终读取的字节数将少于您要求的字节数。然后,您将知道长度。因为UDP保留消息边界,所以不需要为数据包加上长度前缀。这是您在TCP中只需要的,因为它不会这样做。+1很好将代码简化为所需内容的作业
#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;
}