我與這個奇怪的問題鬥爭,其中recvfrom只有當它捕獲目標地址爲255.255.255.255的廣播數據包時才返回。直接發往客戶端的數據包(即使用客戶端IP)將被忽略。recvfrom捕獲只發送到255.255.255.255的數據包
現在一些背景(你可以跳過它,這只是爲了澄清我想要做什麼) - 我試圖實現一個簡單的BOOTP客戶端。我能夠創建BOOTREQUEST,並且服務器用正確的BOOTREPLY(使用wireshark和使用libpcap編寫的簡單分析器進行檢查)回覆它。但是,即使我在wireshark中看到答覆,但我無法在客戶端中收到它,因爲它將客戶端的IP地址用作目標。
我試圖在網絡上,我可以從其他計算機捕獲BOOTP數據包以及。我發現recvfrom可以接收帶廣播地址的BOOTREPLY包。壞事是這些不是我的,因爲我允許服務器使用單播進行回覆。
我使用的代碼:
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0) {
std::cerr << "Cannot create socket" << std::endl;
return;
}
int broadcastON = 1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcastON, sizeof(broadcastON));
sockaddr_in recv_address;
memset((char *) &recv_address, 0, sizeof(recv_address));
recv_address.sin_family = AF_INET;
recv_address.sin_port = htons(68);
recv_address.sin_addr.s_addr = htonl(INADDR_ANY);
int recv_sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (recv_sockfd < 0)
{
std::cerr << "Cannot create socket" << std::endl;
return;
}
if (bind(recv_sockfd, (sockaddr *) &recv_address, sizeof(recv_address)) < 0)
{
std::cerr << "Cannot bind socket" << std::endl;
perror("bind");
return;
}
sniff_bootp packet = createBootpPacket(mac);
sockaddr_in server_address;
memset((char *) &server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(67);
server_address.sin_addr.s_addr = htonl(INADDR_BROADCAST);
if (sendto(sockfd, &packet, sizeof(packet),0,(sockaddr *) &server_address, sizeof(server_address)) < 0)
{
perror("sendto");
return;
}
char msg[512];
while(1)
{
sockaddr_in source_address;
unsigned int cli_addr_len = sizeof(source_address);
// HERE IS THE PROBLEM
// returns only if the destination is broadcast
int msg_length = recvfrom(recv_sockfd, msg, 512, 0, (sockaddr *) &source_address, &cli_addr_len);
if (msg_length < 0) {
perror("rcvfrom");
continue;
}
因此,您的防火牆阻止UDP,除了廣播?簡單的解釋。 –
我沒有啓用防火牆,所以不,這不是。而且,bootpc客戶端按預期工作。實際上,除了本代碼中的recv之外,其他一切都按預期工作。我只是不明白爲什麼UDP recv在其他地方工作,但不在這裏。 – stativ