Ich habe ein Geräteerkennungsprogramm geschrieben, das im Client- oder Servermodus ausgeführt werden kann. Im Client-Modus sendet es ein UDP-Broadcast-Paket an 255.255.255.255 an Port 30000 und wartet dann auf Antworten auf Port 30001. Im Server-Modus wartet es auf UDP-Broadcast auf Port 30000 und sendet ein UDP-Broadcast-Paket an 255.255.255.255 auf Port 30001 In Beantwortung.Wie empfange ich eine UDP-Sendung gesendet an 255.255.255.255 mit Boost Asio?
Wenn ich dieses Programm auf 2 Geräten mit den IP-Adressen 192.168.10.61 und 192.168.10.62 starte, funktioniert alles einwandfrei. Der Sinn dieses Programms besteht darin, dass Geräte mit unbekannten IP-Adressen sich gegenseitig erkennen können, solange sie mit demselben physikalischen Netzwerk verbunden sind. Um das zu testen, änderte ich die IP-Adresse des ersten Geräts in etwas zufälliges wie 12.34.56.42/255.255.240. Und jetzt hört es auf zu arbeiten.
Mit tcpdump auf der 192.168.10.62 Maschine kann ich sehen, dass das UDP-Paket von der 12.134.56.42 Maschine empfangen wurde:
# tcpdump -i eth0 port 30000 -c 1 -v
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:38:02.552427 IP (tos 0x0, ttl 64, id 18835, offset 0, flags [DF], proto UDP (17), length 49)
12.34.56.42.56815 > 255.255.255.255.30000: UDP, length 21
1 packet captured
6 packets received by filter
0 packets dropped by kernel
aber meine Entdeckung Programm nicht mehr erhält es. Dies ist der Code, den ich die UDP-Broadcast-Pakete empfangen bin mit:
int WaitForPacket(uint16_t portNum, vector<char>& udpBuf, udp::endpoint& remoteEndpoint, const chrono::milliseconds timeout)
{
io_service ioService;
udp::socket socket(ioService, udp::endpoint(boost::asio::ip::address_v4::any(), portNum));
socket.set_option(socket_base::broadcast(true));
boost::system::error_code error;
int numBytes = receive_from(socket, buffer(udpBuf), remoteEndpoint, error, timeout);
if (error && error != error::message_size && error != error::timed_out)
{
printf("Got error: %s\n", error.message().c_str());
return -1;
}
return numBytes;
}
/*
* The boost asio library does not provide a blocking read with timeout function so we have to roll our own.
*/
int receive_from(
boost::asio::ip::udp::socket& socket,
const boost::asio::mutable_buffers_1& buf,
boost::asio::ip::udp::endpoint& remoteEndpoint,
boost::system::error_code& error,
chrono::milliseconds timeout)
{
volatile bool ioDone = false;
int numBytesReceived = 0;
boost::asio::io_service& ioService = socket.get_io_service();
socket.async_receive_from(buf, remoteEndpoint,
[&error, &ioDone, &numBytesReceived](const boost::system::error_code& errorAsync, size_t bytesReceived)
{
ioDone = true;
error = errorAsync;
numBytesReceived = bytesReceived;
});
this_thread::sleep_for(chrono::milliseconds(100));
ioService.reset();
ioService.poll_one();
auto endTime = chrono::system_clock::now() + timeout;
while (!ioDone)
{
ioService.reset();
this_thread::sleep_for(chrono::milliseconds(100));
auto now = chrono::system_clock::now();
if (now > endTime)
{
socket.cancel();
error = error::timed_out;
return 0;
}
ioService.poll_one();
}
ioService.reset();
return numBytesReceived;
}
ich ähnliche Fragen auf Stack-Überlauf überprüft und festgestellt, einige, die die Aufnahmebuchse gesagt hat INADDR_ANY um gebunden sein Broadcast-Pakete zu empfangen. Ich habe ursprünglich den Sockel wie diese udp::socket socket(ioService, udp::endpoint(udp::v4(), portNum));
erstellt, aber jetzt geändert, um stattdessen ip::address_v4::any()
zu verwenden. Das machte keinen Unterschied.
Kann mir jemand sagen, was ich ändern muss, um das UDP-Broadcast-Paket wie erwartet zu empfangen?
Ich führe dies auf iMX6-Geräten mit Linux und bin Compiling mit Boost 1.58.
Sie empfangen keine Datagramme, da Sie den Computer automatisch von der lokalen Netzwerkadresse ausschließen, indem Sie die erste Adresse in 12.34.56.42/255.255.240 ändern. Und da die Übertragung nur in LAN-Umgebungen funktioniert, erhalten Sie die Nachricht nicht vollständig. Ihr Computer ist möglicherweise mit dem gleichen Netzwerk mit einer gefälschten IP-Adresse verbunden, und diese gefälschte IP-Adresse ist der Grund dafür, dass die Broadcastnachricht nicht vollständig empfangen wird. – Ivan86
Möglicherweise müssen Sie ein privates Netzwerk für die erkennbaren Geräte einrichten, mit denen alle zuvor verbunden waren, aber das ist nicht wirklich eine Entdeckung. Sie können jedoch Ihr WLAN offen lassen und dies auf Besucher anwenden, die eine Verbindung zu Ihrem Router herstellen. – Ivan86
Eine Möglichkeit, mit beliebigen Adressen umzugehen, wäre, die IP-Adresse des Absenders in den Broadcast-Paketen manuell auf 0.0.0.0 zu setzen (das ist im Grunde auch, wie DHCP funktioniert). Frag mich nicht, wie ich das mit Boost erreichen kann. Vielleicht https://stackoverflow.com/questions/28196466/in-boost-asio-how-can-i-set-the-source-ip-address-to-impersonate-another-server ist hilfreich, soweit ich sehen kann . –