Boost UDP recvfrom无法接收网络数据包问题求助
问题排查与修复建议
1. 修正接收超时的错误设置
你当前使用了Boost Asio内部detail命名空间下的socket选项,这属于未公开的实现细节,容易导致超时设置失效。换成官方推荐的方式配置超时:
将Start()中的超时代码替换为:
boost::asio::socket_base::receive_timeout option(std::chrono::milliseconds(2000)); boostSocket->set_option(option);
如果仅针对Windows平台,也可以用timeval结构体:
timeval tv = {2, 0}; // 2秒超时 boostSocket->set_option(boost::asio::socket_base::receive_timeout(tv));
2. 调整Start()函数的操作顺序
io_service.run()在没有异步任务时会直接返回,你当前所有操作都是同步的,完全不需要提前调用它。删掉Start()里的io_service.run(),调整后的代码如下:
void UdpLayer::Start() { boostSocket = std::make_shared<ip::udp::socket>(io_service); deviceEndpoint = ip::udp::endpoint(ip::address::from_string(ip), port); boostSocket->open(ip::udp::v4()); boostSocket->connect(deviceEndpoint); // 正确设置接收超时 boost::asio::socket_base::receive_timeout option(std::chrono::milliseconds(2000)); boostSocket->set_option(option); }
3. 改用receive替代receive_from
因为你已经调用connect将UDP socket与目标端点绑定,直接用receive就能接收来自该端点的数据,无需额外指定端点参数,代码更简洁可靠:
try { int sz = boostSocket->receive(buffer(recv_buffer)); if(sz > 0) { std::cout << "收到回复,长度: " << sz << std::endl; device->ParsePacket(recv_buffer, sz); } } catch (std::exception& ex) { std::cout << "\n异常: " << ex.what() << "\n\n"; }
4. 确认本地端口匹配
虽然Wireshark显示设备已回复,需确认回复的目标端口是否与Boost程序的本地端口一致。如果MFC程序使用固定本地端口,而你的Boost程序用随机端口,设备可能会回复到固定端口。此时给Boost socket绑定固定端口:
// 在Start()的open之后、connect之前添加绑定代码 // 替换为MFC程序使用的本地端口 ip::udp::endpoint local_endpoint(ip::udp::v4(), 12345); boostSocket->bind(local_endpoint);
5. 移除无效的shutdown操作
UDP协议不支持shutdown操作,boostSocket->shutdown(ip::udp::socket::shutdown_both)完全无效,删掉该行代码,直接关闭socket即可:
void UdpLayer::Terminate() { if (boostSocket) { boostSocket->close(); boostSocket.reset(); } io_service.stop(); }
内容的提问来源于stack exchange,提问作者Ricardo Ramos
相关产品推荐
相关产品推荐

