Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/26.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++ 在Linux下,async_receive_from在几个数据包之后停止接收_C++_Linux_Udp_Boost Asio - Fatal编程技术网

C++ 在Linux下,async_receive_from在几个数据包之后停止接收

C++ 在Linux下,async_receive_from在几个数据包之后停止接收,c++,linux,udp,boost-asio,C++,Linux,Udp,Boost Asio,我有一个设置,每200ms(5fps)有多个对等点广播udp数据包(包含图像) 在Windows下,当以外部流的形式接收本地流时,相同的代码(除了Windows XP中的socket->cancel();,请参见代码中的注释)在Linux下会产生相当奇怪的行为: 由另一台机器发送的前几个(5~7)数据包(当该机器开始流传输时)按预期接收 在此之后,在不规则的长间隔(12s、5s、17s等)后接收来自另一台机器的数据包,或获得超时(在20秒后定义)。在某些时刻,再次出现预期的(3~4)个数据包的

我有一个设置,每200ms(5fps)有多个对等点广播udp数据包(包含图像)

在Windows下,当以外部流的形式接收本地流时,相同的代码(除了Windows XP中的
socket->cancel();
,请参见代码中的注释)在Linux下会产生相当奇怪的行为:

  • 由另一台机器发送的前几个(5~7)数据包(当该机器开始流传输时)按预期接收
  • 在此之后,在不规则的长间隔(12s、5s、17s等)后接收来自另一台机器的数据包,或获得超时(在20秒后定义)。在某些时刻,再次出现预期的(3~4)个数据包的突发
  • 机器本身发送的数据包仍按预期接收
使用Wireshark,我将本地数据包和外部数据包视为应该到达的数据包,在连续数据包之间有正确的时间间隔。当本地计算机仅侦听单个其他流且本地流被禁用时,该行为也会出现

这是来自接收者的一些代码(包括下面建议的一些更新,谢谢!):

Receiver::Receiver(端口p)
{
这个->端口=p;
此->停止=错误;
}
int Receiver::run()
{
io_服务io_服务;
boost::asio::ip::udp::套接字(
io_服务,
boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(),
这个->端口);
当(!停止)
{
常数int bufflength=65000;
int超时=20000;
char sockdata[bufflength];
boost::asio::ip::udp::endpoint远程\u端点;
int rcvd;
bool read\u success=此->接收\u超时(
sockdata、bufflength、rcvd和socket、远程_端点、超时);
如果(读成功)
{

std::cout好的,您正在做的是,当您调用
receive\u with\u timeout
时,您正在设置两个异步请求(一个用于recv,一个用于超时)。当第一个请求完成时,您将取消另一个请求

但是,您永远不会调用
ioservice::run_one()
再次调用,以允许其回调完成。当您取消boost::asio中的操作时,它会调用处理程序,通常带有一个错误代码,指示该操作已中止或取消。在这种情况下,我相信在销毁deadline服务后,会有一个处理程序悬空,因为它在堆栈上有一个指向st的指针结果如何

解决方案是在退出函数之前再次调用run_one()以处理取消的回调结果。您还应该检查传递给超时处理程序的错误代码,并且只有在没有错误时才将其视为超时


另外,如果你确实有一个超时,你需要执行
run\u one
,这样来自
处理程序的
async\u recv\u可以执行,并报告它被取消了。

在使用Xubuntu 12.04而不是使用Ubuntu 10.04进行了一次干净的安装之后,一切都按照预期进行了。可能是因为新的inst所有这些都运行一个更新的内核,可能是通过改进的网络?无论如何,用更新版本的发行版重新安装解决了我的问题


如果其他人在使用旧内核时出现意外的网络行为,我建议在安装了新内核的系统上尝试。

非常感谢您的建议!不幸的是,他们没有为我提供解决方案。我希望我可以添加更多内容,但症状仍然完全相同。发布演示如果您希望我们提供帮助,则会出现问题。特别是,如果没有
Receiver
类定义或
main()
,我们无法编译您发布的有限代码。
Receiver::Receiver(port p)
{
  this->port = p;
  this->stop = false;
}

int Receiver::run()
{
  io_service io_service;
  boost::asio::ip::udp::socket socket(
    io_service,
    boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(),
    this->port));
  while(!stop)
  {
    const int bufflength = 65000;
    int timeout = 20000;
    char sockdata[bufflength];
    boost::asio::ip::udp::endpoint remote_endpoint;
    int rcvd;

    bool read_success = this->receive_with_timeout(
           sockdata, bufflength, &rcvd, &socket, remote_endpoint, timeout);

    if(read_success)
    {
      std::cout << "read succes " << remote_endpoint.address().to_string() << std::endl;
    }
    else
    {
      std::cout << "read fail" << std::endl;
    }
  }
  return 0;
}

void handle_receive_from(
  bool* toset, boost::system::error_code error, size_t length, int* outsize)
{
  if(!error || error == boost::asio::error::message_size)
  {
    *toset = length>0?true:false;
    *outsize = length;
  }
  else
  {
    std::cout << error.message() << std::endl;
  }
}

// Update: error check
void handle_timeout( bool* toset, boost::system::error_code error)
{
  if(!error)
  {
    *toset = true;
  }
  else
  {
    std::cout << error.message() << std::endl;
  }
}

bool Receiver::receive_with_timeout(
  char* data, int buffl, int* outsize,
  boost::asio::ip::udp::socket *socket,
  boost::asio::ip::udp::endpoint &sender_endpoint, int msec_tout)
{
  bool timer_overflow = false;
  bool read_result = false;

  deadline_timer timer( socket->get_io_service() );

  timer.expires_from_now( boost::posix_time::milliseconds(msec_tout) );
  timer.async_wait( boost::bind(&handle_timeout, &timer_overflow,
    boost::asio::placeholders::error) );

  socket->async_receive_from(
    boost::asio::buffer(data, buffl), sender_endpoint,
    boost::bind(&handle_receive_from, &read_result,
    boost::asio::placeholders::error,
    boost::asio::placeholders::bytes_transferred, outsize));

  socket->get_io_service().reset();

  while ( socket->get_io_service().run_one())
  {
    if ( read_result )
    {
      timer.cancel();
    }
    else if ( timer_overflow )
    {
      //not to be used on Windows XP, Windows Server 2003, or earlier
      socket->cancel();
      // Update: added run_one()
      socket->get_io_service().run_one();
    }
  }
  // Update: added run_one()
  socket->get_io_service().run_one();
  return read_result;
}