2016-12-07 10 views
0

Я тестирую простую установку сокета, в которой сервер прослушивает указанный порт, а клиент отправляет широковещательный пакет, который должен быть получен этим сервером.UDP WinSock - не принимать пакеты широковещания

Эта настройка работает нормально при отправке сообщений напрямую (то есть не в режиме широковещания), но при широковещательном рассылке пакет никогда не принимается на сервере.

Часть кода (подстриженной вниз с проверки ошибок удалена для простоты):

// Client (broadcast sender) 

// Create and bind the client socket 
clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

sockaddr_in sockAddr; 
sockAddr.sin_family = AF_INET; 
sockAddr.sin_port = htons(5678); 
sockAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); 

bind(clientSocket, (sockaddr*)(&sockAddr), sizeof(sockAddr)); 

u_long uMode = 1; 
ioctlsocket(clientSocket, FIONBIO, &uMode); 

char broadcast = 1; 
setsockopt(clientSocket, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast)); 

// ... 

// Send the packet 
sockaddr_in sockAddress; 
sockAddress.sin_family = AF_INET; 
sockAddress.sin_addr.S_un.S_addr = htonl(INADDR_BROADCAST); 
sockAddress.sin_port = htons(5679); 

char const* pPacket = "Test"; 
size_t uPacketSize = strlen(pPacket) + 1; 

sendto(clientSocket, pPacket, (int)uPacketSize, 0, (sockaddr*)&sockAddress, sizeof(sockAddress)); 

-

// Server (listener) 

// Create and bind the server socket 
serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 

sockaddr_in sockAddr; 
sockAddr.sin_family = AF_INET; 
sockAddr.sin_port = htons(5679); 
sockAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); 

bind(serverSocket, (sockaddr*)(&sockAddr), sizeof(sockAddr)); 

u_long uMode = 1; 
ioctlsocket(serverSocket, FIONBIO, &uMode); 

// ... 

char pBuffer[1024]; 
while (true) 
{ 
    int iRecvSize = recv(serverSocket, pBuffer, 1024, 0); 
    if (iRecvSize) 
    { 
     printf("Received packet\n"); 
    } 
} 
+0

Возможно, вы захотите добавить проверку ошибок для большего количества функций, таких как, например, вызовы 'setsockopt'. –

+0

Вы * также * необходимо установить опцию 'SO_BROADCAST' в сокет, который вы хотите * принять * в эфир. –

+0

@Someprogrammerdude У меня есть проверка ошибок в фактическом коде, я просто удалил его для этого вопроса. Ни одна из функций не возвращает никаких ошибок (за исключением случайного WSAEWOULDBLOCK, который следует ожидать для неблокирующих сокетов). Я думаю, что я попытался установить SO_BROADCAST на ресивер, но я попробую еще раз и посмотрю, поможет ли это. – yothsoggoth

ответ

0

(Должно быть комментарием, но моя репутация не достаточно высок)

Я не знаю, относится ли это к вам, но существует неинтуитивное поведение с трансляциями в последних версиях Windows. Если у вас есть несколько адаптеров физических Ethernet, программы будут приниматься только на «привилегированный» интерфейсе (где «предпочтение» определяются таблицей маршрутизации Windows')

Смотрите следующее для объяснения и возможного исправления: https://github.com/dechamps/WinIPBroadcast

Еще одним временным решением было бы отключить все другие сетевые адаптеры, чтобы убедиться, что широковещательная передача получена на правильном (в настройках панели управления/сети и общего доступа/изменения адаптера).

+0

Я попытался отключить все, кроме одного сетевого адаптера, но результат был тот же - пакет никогда не получил. Будет ли эта проблема также влиять на тестирование локально (т. Е. С клиентом и сервером, работающим в отдельных потоках одного и того же процесса)? – yothsoggoth

+0

@yothsoggoth Я не думаю, что у меня была проблема локально, но я тестировал два разных процесса. Я не уверен, какое поведение будет для двух потоков одного и того же приложения. Я могу только предложить Wireshark, если вы еще не используете его для отладки. – user1243123