2016-12-07 5 views
0

Je teste une configuration de socket simple dans laquelle un serveur écoute sur un port spécifié, et un client envoie un paquet de diffusion qui devrait être reçu par ce serveur.UDP WinSock - Ne pas recevoir les paquets de diffusion

Cette configuration fonctionne correctement lors de l'envoi direct de messages (c'est-à-dire sans diffusion), mais lors de la diffusion du paquet n'est jamais reçu sur le serveur.

Une partie du code (dégrossi avec contrôle d'erreurs supprimées, pour simplifier):

// 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

Vous pouvez ajouter une vérification d'erreur pour plus de fonctions, comme par exemple les appels 'setsockopt'. –

+0

Vous devez également définir l'option 'SO_BROADCAST' sur le socket que vous voulez * recevoir *. –

+0

@Someprogrammerdude J'ai une erreur de vérification dans le code réel, je l'ai juste supprimé pour cette question. Aucune des fonctions ne retourne d'erreur (à l'exception du WSAEWOULDBLOCK occasionnel, qui est à prévoir pour les sockets non bloquantes). Je pense que j'ai essayé de définir SO_BROADCAST sur le récepteur, mais je vais essayer encore et voir si cela aide. – yothsoggoth

Répondre

0

(Devrait être un commentaire, mais ma réputation est pas assez élevé)

Je ne sais pas si cela s'applique à vous, mais il y a un comportement non-intuitif avec les diffusions sur les versions récentes de Windows. Si vous disposez de plusieurs cartes Ethernet physiques, les émissions ne seront reçus sur l'interface « préférée » (où « préférence » est déterminé par la table de routage Windows)

Voir ce qui suit pour une explication et fixer le potentiel: https://github.com/dechamps/WinIPBroadcast

Une autre solution temporaire serait de désactiver toutes les autres cartes réseau pour s'assurer que la diffusion est reçue sur la bonne (dans Panneau de configuration/Centre Réseau et partage/Modifier les paramètres de l'adaptateur).

+0

J'ai essayé de désactiver tous les adaptateurs sauf un, mais le résultat était le même - le paquet n'est jamais reçu. Ce problème affecte-t-il également les tests localement (c'est-à-dire que le client et le serveur s'exécutent dans des threads distincts du même processus)? – yothsoggoth

+0

@yothsoggoth Je ne pense pas avoir eu le problème localement mais j'ai testé avec 2 processus différents. Je ne suis pas sûr de ce que le comportement serait pour 2 threads de la même application. Je ne peux que suggérer Wireshark si vous ne l'utilisez pas déjà pour déboguer. – user1243123