我有一个设置与多个同行广播udp数据包(包含图像)每200毫秒(5fps)。
虽然接收两个本地stream作为外部stream在Windows下工作正常,相同的代码(除了在Windows XP中的socket->cancel();请参阅代码中的评论)在Linux下产生相当奇怪的行为:
如预期那样接收由另一台机器(当该机器开始stream式传输时)发送的前几个(5〜7)数据包;
在此之后,来自另一台机器的数据包在不规则,长时间间隔(12s,5s,17s,…)之后被接收,或者超时(在20秒之后定义)。 在某些时刻,如预期的那样再次出现(3〜4)个分组。
机器本身发送的数据包仍在按预期收到。
使用Wireshark,我看到两个本地的外部数据包到达,因为它们应该在连续的包之间有正确的时间间隔。 当本地计算机只监听另一个stream时,行为也会出现,本地stream被禁用。
这是从接收器的一些代码(有一些更新如下build议,谢谢!):
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; }
当计时器超过20秒时,将返回错误消息“操作已取消”,但很难获得关于正在进行的任何其他信息。
任何人都可以确定一个问题,或者给我一些提示,以获得更多有关错误的信息? 任何帮助表示赞赏。
好的,当你调用receive_with_timeout ,你正在设置两个异步请求(一个是recv,一个是timeout)。 当第一个完成时,你取消另一个。
但是,您再也不会调用ioservice::run_one()来完成回调。 当你在boost :: asio中取消一个操作时,它会调用处理程序,通常会有一个错误代码指示操作已被中止或取消。 在这种情况下,我相信一旦你销毁了最后期限的服务,你就有了一个处理器,因为它有一个指向堆栈的指针来存储结果。
解决方法是在退出函数之前再次调用run_one()来处理取消的回调结果。 您还应该检查传递给您的超时处理程序的错误代码,只有在没有错误时才将其视为超时。
此外,如果您确实有超时,则需要执行run_one以便可以执行async_recv_from处理程序,并报告它已被取消。
在使用Xubuntu 12.04进行全新安装而不是使用Ubuntu 10.04进行旧安装之后,现在一切都按预期工作。 也许是因为新安装运行一个新的内核,可能改善了网络? 无论如何,重新安装一个较新版本的发行解决了我的问题。
如果其他人得到意外的网络行为与旧的内核,我会建议尝试在一个新的内核安装系统。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。