为什么此程序没有接收到预期的UDP数据包
Why does this program not receive the expected UDP packets?
我正在尝试使用Boost asio接收UDP数据包。我的代码基于asio文档中的这个阻塞UDP客户端示例。
我正试图从C6655 TI DSP接收一个类似BOOTP的UDP数据包,该数据包以3秒的间隔发送。我让Wireshark在我的程序监听的同一个界面上观看,它可以看到数据包到达(请参阅下面从Wireshark导出的确切数据包数据(。数据包实际上并不是来自DSP的,我用tcpdump
捕获了一个,我正在用packeth从树莓派上模拟它。
但是,我的程序没有接收到数据包。它有一个4秒的超时(因为DSP每3秒广播一次(。如果它达到超时,它会打印一条消息,否则它应该打印接收到的字节数。该程序的完整(可编译(源代码如下(约100行(。
使用参数192.168.5.122 67 4000
调用该命令,这意味着在192.168.5.122:67上侦听,超时时间为4000毫秒。
编辑:除了下面的代码外,我还尝试将其作为我的端点:udp::endpoint listen_endpoint(boost::asio::ip::address_v4::any(), atoi(argv[2]));
以及某个搜索结果建议的IP地址0.0.0.0
。
我还添加了以下内容,但没有用:
boost::asio::socket_base::broadcast option(true);
socket_.set_option(option);
我确实有一个程序能够正确地接收这个数据包,它是使用Berkeley套接字编写的。除了绑定到INADDR_ANY之外,它并没有做任何特别的事情。
以下是完整的程序:
//
// blocking_udp_client.cpp
// ~~~~~~~~~~~~~~~~~~~~~~~
//
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/udp.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include <iostream>
using boost::asio::deadline_timer;
using boost::asio::ip::udp;
class listener
{
public:
listener(const udp::endpoint& listen_endpoint)
: socket_(io_service_, listen_endpoint)
, deadline_(io_service_)
{
deadline_.expires_at(boost::posix_time::pos_infin);
check_deadline();
}
std::size_t receive(const boost::asio::mutable_buffer& buffer, boost::posix_time::time_duration timeout, boost::system::error_code& ec)
{
deadline_.expires_from_now(timeout);
ec = boost::asio::error::would_block;
std::size_t length = 0;
socket_.async_receive(boost::asio::buffer(buffer), boost::bind(&listener::handle_receive, _1, _2, &ec, &length));
// TODO: The following do/while is hinky. Does run_one() need to happen before the comparison?
do io_service_.run_one();
while (ec == boost::asio::error::would_block);
return length;
}
private:
void check_deadline()
{
if (deadline_.expires_at() <= deadline_timer::traits_type::now())
{
// cancel() won't work on XP. Something about using close() instead... Look it up. I'm doing this on Win10.
socket_.cancel();
deadline_.expires_at(boost::posix_time::pos_infin);
}
deadline_.async_wait(boost::bind(&listener::check_deadline, this));
}
static void handle_receive(const boost::system::error_code& ec, std::size_t length, boost::system::error_code* out_ec, std::size_t* out_length)
{
*out_ec = ec;
*out_length = length;
}
private:
boost::asio::io_service io_service_;
udp::socket socket_;
deadline_timer deadline_;
};
int main(int argc, char* argv[])
{
try
{
if (argc != 4)
{
std::cerr << "Usage: blocking_udp_timeout <listen_addr> <listen_port> <timeout_ms>n";
return 1;
}
udp::endpoint listen_endpoint(boost::asio::ip::address::from_string("0.0.0.0"), atoi(argv[2]));
std::cout << "Endpoint: " << listen_endpoint << std::endl;
auto timeout = atoi(argv[3]);
std::cout << "Timeout : " << timeout << std::endl;
listener c(listen_endpoint);
for (;;)
{
char data[1024];
boost::system::error_code ec;
auto n = c.receive(boost::asio::buffer(data), boost::posix_time::milliseconds{timeout}, ec);
if (ec)
{
std::cout << "Receive error: " << ec.message() << "n";
}
else
{
std::cout << "Received " << n << " bytes." << std::endl;
}
}
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "n";
}
return 0;
}
这是我要收的包裹。这包括以太网帧:
0000 ff ff ff ff ff ff c4 ed ba aa 28 35 08 00 45 00 ..........(5..E.
0010 01 48 00 01 00 00 10 11 a9 a5 00 00 00 00 00 00 .H..............
0020 00 00 00 44 00 43 01 34 00 00 01 01 06 00 12 34 ...D.C.4.......4
0030 56 78 00 01 00 00 00 00 00 00 00 00 00 00 00 00 Vx..............
0040 00 00 00 00 00 00 c4 ed ba aa 28 35 00 00 00 00 ..........(5....
0050 00 00 00 00 00 00 74 69 2d 62 6f 6f 74 2d 74 61 ......ti-boot-ta
0060 62 6c 65 2d 73 76 72 00 00 00 00 00 00 00 00 00 ble-svr.........
0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0090 00 00 00 00 00 00 74 69 2d 62 6f 6f 74 2d 74 61 ......ti-boot-ta
00a0 62 6c 65 2d 30 30 30 37 00 00 00 00 00 00 00 00 ble-0007........
00b0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00e0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0130 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0150 00 00 00 00 00 00 ......
我确实有一个Berkeley套接字实现,可以接收这个数据包(我已经删除了错误处理和其他错误代码(:
{
struct sockaddr_in servaddr;
socklen_t len;
char mesg[RECV_BUFFER_LENGTH];
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(67);
bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
n = recvfrom(sockfd, mesg, RECV_BUFFER_LENGTH, 0, NULL, &len);
}
考虑socket_.cancel()
之后,但在下一次调用socket_.async_receive()
之前会发生什么。如果有任何数据到达;接收处理程序";分配给套接字。当计时器到期时,它会导致run_once()
被调用3次(因为每个async_wait()
、expires_at()
和其他一些会导致取消已分配的处理程序,并导致已分配的处理器被发布到运行队列,错误代码为operation_aborted
(。
您还没有提到您的超时设置为什么。您的代码所基于的示例(Boost文档中的示例(将超时设置为10秒,但您可以对其进行配置。如果超时过紧,这将导致旋转(post->取消前一个->调用前一个处理程序->,并可能在接收数据包时调用socket_.cancel()
。如果是这样的话,你就不必用广播来测试它了。通过点对点连接,您也可以看到它。
编辑:在使用长超时(4000ms(和您的确切代码时,我能够接收到发送的广播。我不得不安装";传统的";netcat,因为BSD netcat已损坏。但是下面的行有效:
echo "hello world" | nc.traditional -b -u 192.168.XXX.255 1500
XXX、 255不是字面上的"255";XXX、 255";。这是我的本地广播地址-nc.bsd中的b选项已损坏(如果您使用上述选项约束nc.bsd,您可以看到原因(。
unix stackexchange nc.tradial提供了一个很好的例子,说明了其他人是如何理解nc.bsd为什么不能进行UDP广播的(-b选项什么都不做(。
PackEth无法发送广播或p-p流量,所以我不会用它来衡量你是否可以发送广播流量。诚然,我对它没有太多经验,所以我不知道它是坏了还是配置不正确。
- 发送固定大小的 UDP 数据包
- 使用C++将UDP数据包存储在Structure中
- 在高数据包速率下最大限度地减少丢弃的 UDP 数据包 (Windows 10)
- Qt 在可预测的秒数后跳过 UDP 数据包
- 高频接收UDP数据包:丢包?
- 为 posix recv 设置超时会导致 udp 数据包丢失吗?
- 了解 UDP 数据包大小限制的 TCP 数据包大小限制以及它在 boost::asio 编程级别的含义
- 获取进入UDP数据包的目标端口
- 操纵Windows Explorer窗口时,UDP数据包会掉落
- C++ 使用 recvmmsg 丢弃 UDP 数据包
- 如何在QT中接收适当的UDP数据包
- 使用ASIO捕获大量UDP数据包
- 如何正确接收多播UDP数据包
- 服务器未收到UDP数据包,花费数小时试图找出问题所在
- 当接收缓冲区几乎满时,阻止UDP数据包被部分截断
- 如何检查UDP数据包是否在发送器上发送
- 使用 QNX 实时操作系统实时接收 UDP 数据包
- 高效地发送UDP数据包流
- 为什么我在使用 winsock 时没有收到 UDP 数据包?
- SDL_net UDP 数据包数据