클라이언트 또는 서버 모드에서 실행할 수있는 장치 검색 프로그램을 작성했습니다. 클라이언트 모드에서는 포트 30000에서 255.255.255.255로 UDP 브로드 캐스트 패킷을 보낸 다음 포트 30001에서 응답을 수신합니다. 서버 모드에서는 포트 30000에서 UDP 브로드 캐스트를 수신하고 UDP 브로드 캐스트 패킷을 포트 30001에서 255.255.255.255로 보냅니다 답으로.부스트 ASIO를 사용하여 255.255.255.255로 보낸 UDP 브로드 캐스트를받는 방법은 무엇입니까?
IP 주소가 192.168.10.61 및 192.168.10.62 인이 장치를 2 대의 장치에서 실행할 때 모두 제대로 작동합니다. 이 프로그램의 요점은 IP 주소가 알려지지 않은 장치가 동일한 물리적 네트워크에 연결되어있는 한 서로를 발견 할 수있게하는 것입니다. 그래서 그것을 테스트하기 위해 첫 번째 장치의 IP 주소를 12.34.56.42/255.255.240과 같이 무작위로 변경했습니다. 그리고 이제는 작동을 멈 춥니 다.
# 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
을하지만 내 검색 프로그램을 더 이상 수신 :
나는 12.134.56.42 기계에서 UDP 패킷이 수신 된 것을 볼 수 192.168.10.62 시스템에 tcpdump를 사용하지 않습니다. 내가 스택 오버플로에서 비슷한 질문을 확인하고 수신 소켓 브로드 캐스트 패킷을 수신하기 위해 INADDR_ANY에 바인드되어야 말했다 몇 가지를 발견
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;
}
이 내가 UDP 브로드 캐스트 패킷을 수신하기 위해 사용하고있는 코드입니다. 나는 원래 udp::socket socket(ioService, udp::endpoint(udp::v4(), portNum));
과 같은 소켓을 만들었지 만 이제는 ip::address_v4::any()
을 사용하도록 변경했습니다. 그것은 아무런 효과가 없었습니다.
예상대로 UDP 브로드 캐스트 패킷을 받기 위해 내가 무엇을 변경해야하는지 알려줄 수 있습니까?
Linux를 실행하는 iMX6 기기에서 실행 중이며 boost 1.58을 사용하여 컴파일 중입니다.
첫 번째 주소를 12.34.56.42/255.255.240으로 변경하면 자동으로 컴퓨터가 로컬 네트워크 주소에서 제외되므로 데이터 그램을 수신하지 못합니다. 그리고 방송은 LAN 환경에서만 작동하기 때문에 이것이 메시지를 완전히받지 못하는 이유입니다. 컴퓨터가 스푸핑 된 IP로 동일한 네트워크에 연결되어있을 수 있으며 스푸핑 된 IP가 브로드 캐스트 메시지를 완전히 수신하지 못하는 이유입니다. – Ivan86
이전의 검색에 모두 연결될 수있는 검색 가능한 장치에 대해 개인 네트워크를 설정해야하지만 실제로는 검색이 아닙니다. 그래도 할 수있는 것은 무선 랜을 열린 상태로두고 라우터에 연결하는 방문자에게이 기능을 적용하는 것입니다. – Ivan86
임의의 주소를 처리하는 한 가지 방법은 수동으로 브로드 캐스트 패킷의 보낸 사람 IP 주소를 0.0.0.0으로 설정하는 것입니다 (이는 기본적으로 DHCP가 작동하는 방식입니다). 부스트로 이것을 달성하는 방법을 묻지 마십시오. 어쩌면 https://stackoverflow.com/questions/28196466/in-boost-asio-how-can-i-set-the-source-ip-address-to-impersonate-another-server가 도움이됩니다. . –