Boost asio kullanarak UDP paketi almaya çalışıyorum. Kodum this blocking UDP client example from the asio documentation'un temel alınmıştır.Bu program neden beklenen UDP paketlerini almıyor?
3 saniyelik aralıklarla iletilen bir C6655 TI DSP'den BOOTP benzeri bir UDP paketi almaya çalışıyorum. Programımın dinlediği aynı arabirimi izleyen Wireshark'ım var ve gelen paketleri görebiliyorum (Wireshark'tan aktarılan tam paket veri için aşağıya bakın). Paketler, DSP'den gelen gerçekten değil, ben tcpdump
ile bir tane yakaladım ve ben packeth ile bir Raspberry Pi'den simüle ediyorum. Ancak, programım paketleri almıyor. 4 saniyelik bir zamanaşımı vardır (DSP her 3 saniyede bir yayınladığı için). Zaman aşımına çarparsa, bu etki için bir mesaj yazar, aksi halde alınan bayt sayısını yazdırması gerekir. Programın tam (compilable) kaynak kodu (yaklaşık 100 satır) takip eder.
Komut, 192.168.5.122 67 4000
parametreleriyle çağrılıyor, yani 192.168.5.122:67 üzerinde 4000 milisaniye bir zamanaşımı ile dinleniyor.
Düzenleme: Aşağıdaki kodun yanı sıra, bunu bir noktadan başka bir arama sonucu tarafından önerildiği gibi ve 0.0.0.0
IP adresi olarak denedim.
boost::asio::socket_base::broadcast option(true);
socket_.set_option(option);
düzgün Berkeley yuvalarını kullanarak yazılı bu paketi, alabilecek bir programa sahip yapın:
Ben de boşuna aşağıdaki eklendi. INADDR_ANY'ye bağlanmanın ötesinde, görebileceğim özel bir şey yapmıyor. İşte
//
// 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;
}
aldığım çalışıyorum paket geçerli:
İşte tam programıdır.
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 ......
ben bu paketi alabilecek bir Berkeley yuva uygulama (Ben hata işleme ve diğer çeşitli kod kaldırdık.) Var:
{
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);
}
BOOTP normalde, özel bayraklar gerektiren bir yayın gerektirir. –
@BenVoigt Bunu "boost :: asio" ile nasıl gerçekleştireceğinizi açıklayabilir misiniz? – Steve
Bulduğum diğer bazı arama sonuçlarının önerdiği gibi, '0' (garip görünüyor) bağlantı noktasını dinlemeyi denedim, ancak boşuna. – Steve