我有一个通过以太网广播的设备,使用下面的代码成功接收了数据包。设备还通过WiFi单播相同的数据包,但未收到此消息(在Windows中禁用除WiFi之外的所有其他接口,我收到超时错误)。如果我更改:
address.sin_addr.s_addr = htonl(INADDR_ANY);
到
address.sin_addr.s_addr = inet_addr("192.168.0.13");
它确实是接收数据包的wifi接口的地址。在WireShark中可以看到通过以太网和WiFi传输的数据包,它们之间的唯一区别是目标地址(广播和单播)和ttl。
代码如下:
int main()
{
int iResult;
char recv_buf[4000];
int opt = 1;
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
printf("WSAStartup failed with error: %d\n", err);
return 1;
}
SOCKET handle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
int return_code = 0;
return_code = setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char *>(&opt), sizeof(opt));
std::cout<<"socket option 1 return:" << return_code << std::endl;
DWORD tv = 100;
return_code = setsockopt(handle, SOL_SOCKET, SO_RCVTIMEO, reinterpret_cast<char *>(&tv), sizeof(tv));
std::cout << "socket option 2 return:" << return_code<< std::endl;
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_port = htons(3000);
address.sin_addr.s_addr = htonl(INADDR_ANY);
//address.sin_addr.s_addr = inet_addr("192.168.0.13"); //this works
memset(&address.sin_zero, 0, sizeof(address.sin_zero));
std::cout << "bind return:" << bind(handle, (const sockaddr *)&address, sizeof(sockaddr_in)) << std::endl;
// Receive data until the server closes the connection
do {
Sleep(5000);
iResult = recv(handle, recv_buf, 4000, 0);
if (iResult > 0)
printf("Bytes received: %d\n", iResult);
else if (iResult == 0)
printf("Connection closed\n");
else
printf("recv failed: %d\n", WSAGetLastError());
} while (true);
return 0;
}