c++ - Why does this program not receive the expected UDP packets? -
i trying receive udp packet using boost asio. code based off of this blocking udp client example asio documentation.
i trying receive bootp-like udp packet c6655 ti dsp, being transmitted in 3 second intervals. have wireshark watching same interface program listening on, , can see packets arriving (see below exact packet data, exported wireshark). packets aren't really coming dsp, captured 1 tcpdump
, i'm simulating raspberry pi packeth.
however, program not receive packets. has 4 second timeout (since dsp broadcasts every 3 seconds). if hits timeout, prints message effect, otherwise it's supposed print number of bytes received. full (compilable) source code of program follows (about 100 lines).
the command being invoked parameters 192.168.5.122 67 4000
, means listen on 192.168.5.122:67 4000 millisecond timeout.
edit: in addition code below, tried endpoint: udp::endpoint listen_endpoint(boost::asio::ip::address_v4::any(), atoi(argv[2]));
ip address 0.0.0.0
suggested search result somewhere.
i added following no avail:
boost::asio::socket_base::broadcast option(true); socket_.set_option(option);
i have program able receive packet, written using berkeley sockets. it's not doing special can see, beyond binding inaddr_any.
here complete program:
// // 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: following do/while hinky. run_one() need happen before comparison? 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. using close() instead... up. i'm doing 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); (;;) { 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; }
here packet i'm trying receive. includes ethernet frame:
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 ......
i have berkeley socket implementation can receive packet (i have removed error handling , other misc. code):
{ 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); }
consider happens after socket_.cancel()
, before next call socket_.async_receive()
. if data arrives, there no "receive handler" assigned socket. when timer expires, causes run_once()
called 3 times (because each async_wait()
, expires_at()
, of others cause cancellations of already-assigned handlers , cause already-assigned handlers posted run queue error code operation_aborted
).
you haven't mentioned timeout set to. example on base code (the 1 boost documentation) sets timeout 10 seconds, make configurable. if timeout tight, cause spin (post->cancel previous->call previous handler->post->etc.) , possibly call socket_.cancel()
while receiving packet. if that's case, wouldn't have go far test broadcast. you'd able see point-to-point connection, too.
edit: while using long timeout (4000ms) , exact code, able receive sent broadcast. had install "traditional" netcat because bsd netcat broken. the line below worked:
echo "hello world" | nc.traditional -b -u 192.168.xxx.255 1500
xxx.255 not literally "xxx.255". it's local broadcast address. -b option in nc.bsd broken (you can see why if strace nc.bsd above options).
unix stackexchange nc.traditional has example of how others figured out why nc.bsd cannot udp broadcasts (-b option nothing).
packeth wasn't able to send broadcasts or p-t-p traffic, wouldn't use measure of whether can send broadcast traffic. admittedly, don't have experience it, don't know if it's broken or if don't have configured right.
Comments
Post a Comment