2009-05-26 4 views
3

Iam essayant de créer un serveur itératif basé sur des sockets datagram (UDP). Il appelle se connecter au premier client qu'il obtient à partir du premier appel recvfrom() (oui, je sais que ce n'est pas une connexion réelle). Après avoir servi ce client, je déconnecte le socket UDP (appel de connexion avec AF_UNSPEC) Puis j'appelle recvfrom() pour obtenir le premier paquet du client suivant.Déconnexion et reconnexion d'une socket de datagramme connectée

Maintenant, le problème est, que l'appel de recvfrom() dans la deuxième itération de la boucle renvoie 0. Mes clients n'envoient jamais de paquets vides, donc ce qui pourrait se passer.

C'est ce que fait Iam (pseudocode):

s = socket(PF_INET, SOCK_DGRAM, 0) 

bind(s) 

for(;;) 
{ 
    recvfrom(s, header, &client_address) // get first packet from client 
    connect(s,client_address) // connect to this client 
    serve_client(s); 
    connect(s, AF_UNSPEC); // disconnect, ready to serve next client 
} 

EDIT: J'ai trouvé le bogue dans mon client d'envoyer par mégarde un paquet vide. Maintenant, mon problème est comment faire attendre le client pour être servi au lieu d'envoyer une requête dans nulle part (le serveur est connecté à un autre client et ne sert pas encore d'autre client). Connect() est vraiment complètement inutile sur SOCK_DGRAM

Répondre

3

L'appel à la connexion ne vous empêche pas de recevoir des paquets d'autres hôtes, et ne vous empêche pas de les envoyer. Ne vous embêtez pas, ce n'est pas vraiment utile. CORRECTION: oui, apparemment, cela ne vous empêche pas de recevoir des paquets d'autres hôtes. Mais le faire dans un serveur est un peu idiot parce que tous les autres clients seraient bloqués pendant que vous étiez connecté() à un. Aussi, vous aurez toujours besoin d'attraper "paillettes" qui flottent autour. Il y a probablement des conditions de concurrence associées à connect() sur une socket DGRAM - que se passe-t-il si vous appelez connect et que des paquets d'autres hôtes sont déjà dans le buffer?

De plus, 0 est une valeur de retour valide de recvfrom(), car les paquets vides (aucunes données) sont valides et peuvent exister (en effet, les gens les utilisent souvent). Vous ne pouvez donc pas vérifier si quelque chose a réussi de cette façon.

Selon toute vraisemblance, un paquet de zéro octet était déjà dans la file d'attente.

Votre protocole doit être conçu pour minimiser les risques de mauvaise interprétation d'un datagramme erroné; Pour cette raison, je vous suggère de ne pas utiliser de datagrammes vides et d'utiliser un nombre magique à la place.

Les applications UDP DOIVENT être capables de reconnaître les paquets "chaff" et de les laisser tomber; ils se présenteront tôt ou tard.

+0

Connect définit un filtre interne à partir duquel l'adresse est reçue et envoyée à l'aide de send() ou recv(). recv(): "Pour les sockets SOCK_DGRAM, les données sont extraites du premier datagramme mis en file d'attente pour l'adresse de destination spécifiée dans l'appel de connexion". – codymanix

+0

Vous avez raison, mon client envoyait (en raison d'un bug) un paquet vide. Maintenant j'ai un autre problème. Le client qui doit attendre dans la file d'attente pour être servi envoie son premier paquet de requête (qui n'est jamais reçu du serveur). Ensuite, il essaie de recevoir la réponse et recv renvoie -1. Comment puis-je faire attendre le client? – codymanix

+0

êtes-vous toujours confronté à ce problème (la partie Modifier de votre message) ou est-il résolu en supprimant se connecter. –

0

man connect:

 
... 
If the initiating socket is not connection-mode, then connect() 
shall set the socket’s peer address, and no connection is made. 
For SOCK_DGRAM sockets, the peer address identifies where all 
datagrams are sent on subsequent send() functions, and limits 
the remote sender for subsequent recv() functions. If address 
is a null address for the protocol, the socket’s peer address 
shall be reset. 
... 
+1

Alors quoi? En quoi cela répond-il à ma question? – codymanix

+0

Quelle était la question exactement? –

+0

Désolé si je n'étais pas clair. La question était pourquoi le deuxième appel à recvfrom() renvoie 0. J'ai maintenant trouvé que c'était un bug dans mon code. Mon problème maintenant est comment faire attendre le client pour être servi au lieu de lui laisser envoyer des données dans nowwhere. – codymanix

-1

Juste une correction au cas où quelqu'un stumbples à travers cela comme je l'ai fait. Pour se déconnecter, connect() doit être appelé avec le membre sa_family de sockaddr défini sur AF_UNSPEC. Pas seulement passé AF_UNSPEC.

Questions connexes