OVH Cloud OVH Cloud

Socket UDP en broadcast

83 réponses
Avatar
Thomas Nemeth
Bonjour !

Je cherche à émettre des données (une chaîne de 30 caractères) en
broadcast UDP. Si je sais me débrouiller pour les socket TCP (et encore
je n'ai pas tenté le broadcast), pour les sockets UDP j'ai du mal à voir
comment configurer la socket afin de pouvoir écrire à partir d'une
machine et lire à partir de plusieurs autres.

Jusque-là, pour mes serveurs, je faisais la recette habituelle :
- pour les serveurs :
socket()
setsockopt() pour REUSEADDR et LINGER
bind()
listen()

- pour les clients :
socket()
setsockopt() (idem)
bind()
connect()

Or pour les sockets UDP en broadcast, je ne vois pas trop comment
faire. Pour l'instant (ce qui ne marche pas) :
socket()
setsockopt() pour REUSEADDR et BROADCAST
connect()

Puis write() ou send() pour écrire et read() ou recv() pour lire.

Quelqu'un a-t-il une idée sur la méthode à appliquer ?
Merci d'avance.

Thomas.

10 réponses

1 2 3 4 5
Avatar
Thomas Nemeth
DINH Viêt Hoà a tapoté :


Après avoir fouillé les différentes pages man j'ai des
difficultés à saisir la façon de se servir de bind() et
connect(). Pour socket(), accept(), (set|get)sockopt(),
send[to](), recv[from](), je vois bien mais l'utilité de bind()
et connect() ne me semble pas claire (bien qu'indispensable) et
je les utilise donc de façon robotique sans trop comprendre les
mécanismes sous-jacents.



J'ai fouillé le net un peu plus entre temps :) Des fois je me
ficherait des baffes. M'enfin bon, merci d'avoir répondu.


bind : tu associes les ports/addresses source et destination.
pour le port source, 0 permet d'obtenir un numéro de port libre.

connect: établir la connexion

send: envoyer une donnée
recv: recevoir une donnée


Je me posais une question : une fois qu'on a créé une socket il
semble y avoir 2 possibilités pour y écrire :
- send
- sendto

La page man de send[to] indique que :
Send ne peut être utilisé qu'avec les sockets connectées alors
que sendto et sendmsg peuvent être utilisés tout le temps.

Ce qui me pose pb c'est : est-ce que bind() permet d'utiliser
send() et non sendto() (puisque bind "affecte un <<nom>> à une
socket" mais la page man ne parle pas de <<connexion>>) ?


Avatar
DINH Viêt Hoà

bind : tu associes les ports/addresses source et destination.
pour le port source, 0 permet d'obtenir un numéro de port libre.

connect: établir la connexion

send: envoyer une donnée
recv: recevoir une donnée


Je me posais une question : une fois qu'on a créé une socket il
semble y avoir 2 possibilités pour y écrire :
- send
- sendto

La page man de send[to] indique que :
Send ne peut être utilisé qu'avec les sockets connectées alors
que sendto et sendmsg peuvent être utilisés tout le temps.

Ce qui me pose pb c'est : est-ce que bind() permet d'utiliser
send() et non sendto() (puisque bind "affecte un <<nom>> à une
socket" mais la page man ne parle pas de <<connexion>>) ?


oui, la page de manuel est sans doute très abstraite sur la définition,
vu que ce n'est pas nécessairement de l'IP en-dessous.

Je me corrige moi-même en fait : bind() permet de ne t'assigner que tes
port/adresse source, ce qui te permettra d'envoyer des messages vers
toute destination.

connect() permet d'assigner les port/address destination dans le cas de
TCP.

avec UDP, tu utilises sendto() pour donner les port/addresse
destination.

--
DINH V. Hoa,

"Je suis une merde" -- jyb


Avatar
Marc Boyer
DINH Viêt Hoà a écrit :
C'est quoi un standard ?
Disons qu'actuellement, plein de monde travaille sur le multicast,
et donc sur le multicast fiable. Il y a pas mal de RFC. En cherchant
un peu, je viens de voir que PGM (RFC 3208) est implémenté par
Window serveur 2003. Est-ce que cela en fait un standard ?
Les protocoles de RealNetworks ne sont pas des standards à ma
connaissance, et ils existent quand même. Idem pour les
protocoles de P2P.


RFC 3208 me va bien comme réponse à ma question.


OK

Des broadcast, je ne connais pas, et je ne vois
même pas trop ce que ça voudrait dire.


broadcast = multicast sans filtrage ?


broadcast: envois à tous
multicast: envois à un groupe


De ce que je connais, le broadcast a l'air d'être souvent employé à la
place du multicast pour des émissions vers un groupe. Je connais en fait
peu d'utilisation de broadcast licite.


Ben, c'est un peu comme la distinction octet/char/byte en C,
compilation/édition de lien en prog, expression régulière/rationnelle
en théorie de l'info, etc. Quand on est pas de la partie, la
différence importe peu. Quand on commence à se poser un pb précis,
il faut la faire.

Marc Boyer
--
À vélo, prendre une rue à contre-sens est moins dangeureux
que prendre un boulevard dans le sens légal. À qui la faute ?




Avatar
Thomas Nemeth
DINH Viêt Hoà a tapoté :


Je me posais une question : une fois qu'on a créé une socket il
semble y avoir 2 possibilités pour y écrire :
- send
- sendto

Ce qui me pose pb c'est : est-ce que bind() permet d'utiliser
send() et non sendto() (puisque bind "affecte un <<nom>> à une
socket" mais la page man ne parle pas de <<connexion>>) ?


Je me corrige moi-même en fait : bind() permet de ne t'assigner que
tes port/adresse source, ce qui te permettra d'envoyer des messages
vers toute destination.


Ok...


avec UDP, tu utilises sendto() pour donner les port/addresse
destination.


Groumph :(
Pas possible de faire un bind() suivi de plusieurs send() dans ce
cas ?

À l'heure actuelle je pourrais donc faire :
- serveur : émet en permanence des données
socket()
setsockopt()
while (cond) sendto()
- clients : reçoivent en permanence ces données.
socket()
setsockopt()
while (cond) recvfrom()

Mais si je veux pouvoir faire en sorte qu'un des clients envoie une
commande de changement de type de données au serveur, il faut que le
serveur puisse écouter... Or écouter sur du broadcast alors qu'on y
écrit soi-même peut être un poil gênant, non ? Le serveur risque de
recevoir ses propres messages et donc croire qu'il reçoit une
demande de connexion.

Le fait que les autres clients recoivent la commande n'est pas un pb
puisqu'ils pourront faire un traitement discriminatif sur les
données reçues.

Y aurait-il la possibilité pour le serveur de faire un truc dans le
genre :
socket()
setsockopt()
bind() // sur l'adresse locale
listen()/accept() // dans un thread
while (cont) sendto(broadcast) // dans un autre thread


Thomas.


Avatar
Thomas Nemeth
DINH Viêt Hoà a tapoté :


Je me posais une question : une fois qu'on a créé une socket il
semble y avoir 2 possibilités pour y écrire :
- send
- sendto

Ce qui me pose pb c'est : est-ce que bind() permet d'utiliser
send() et non sendto() (puisque bind "affecte un <<nom>> à une
socket" mais la page man ne parle pas de <<connexion>>) ?


Je me corrige moi-même en fait : bind() permet de ne t'assigner que
tes port/adresse source, ce qui te permettra d'envoyer des messages
vers toute destination.


Ok...


avec UDP, tu utilises sendto() pour donner les port/addresse
destination.


Groumph :(
Pas possible de faire un bind() suivi de plusieurs send() dans ce
cas ?

À l'heure actuelle je pourrais donc faire :
- serveur : émet en permanence des données
socket()
setsockopt()
while (cond) sendto()
- clients : reçoivent en permanence ces données.
socket()
setsockopt()
while (cond) recvfrom()

Mais si je veux pouvoir faire en sorte qu'un des clients envoie une
commande de changement de type de données au serveur, il faut que le
serveur puisse écouter... Or écouter sur du broadcast alors qu'on y
écrit soi-même peut être un poil gênant, non ? Le serveur risque de
recevoir ses propres messages et donc croire qu'il reçoit une
demande de connexion.

Le fait que les autres clients recoivent la commande n'est pas un pb
puisqu'ils pourront faire un traitement discriminatif sur les
données reçues.

Y aurait-il la possibilité pour le serveur de faire un truc dans le
genre :
socket()
setsockopt()
bind() // sur l'adresse locale
recv() // dans un thread
while (cont) sendto(broadcast) // dans un autre thread


Thomas.


Avatar
Laurent Wacrenier
DINH Viêt Hoà écrit:
le multicast actuel ne gère pas la fiabilité ni le contrôle de flux.


Le contrôle de flux se gère en point à point. Celui qui n'a pas reçu
demande une réémission à celui qui écrit.

Avatar
Christophe Blaess


avec UDP, tu utilises sendto() pour donner les port/addresse
destination.



Groumph :(
Pas possible de faire un bind() suivi de plusieurs send() dans ce
cas ?



Il est possible d'utiliser connect() sur une socket UDP
(en donnant l'adresse d'un correspondant). Dans ce cas
on pourra utiliser send() et recv() (voire write() et read())
à la place de sendto() et recvfrom(). Le noyau s'assurera qu'il
n'y a de dialogue qu'avec le correspondant indiqué.

Note que l'appel connect() sur une socket UDP est une opération
purement interne au système, rien n'est émis sur le réseau.

Pour déconnecter ultérieurement une socket UDP (et pouvoir la
connecter vers un autre correspondant), il faut faire qqchose
comme :

struct sockaddr addr;
addr.sa_family = AF_UNSPEC;
connect(socket, & addr, sizeof(addr));

--
Christophe Blaess
http://www.blaess.fr/christophe/


Avatar
Marc Boyer
Le 17-06-2005, Laurent Wacrenier a écrit :
DINH Viêt Hoà écrit:
le multicast actuel ne gère pas la fiabilité ni le contrôle de flux.


Le contrôle de flux se gère en point à point. Celui qui n'a pas reçu
demande une réémission à celui qui écrit.


Controle d'erreur ou controle de flux ?
Les solutions de controle d'erreur qui cherche à pouvoir passer
à l'échelle ne demandent justement pas la ré-émission à
l'émetteur, mais plutôt à un voisin l'ayant reçu, ou
autres mécanismes de filtrage.
Le controle de flux, c'est à ma connaissance balbutiant.

Marc Boyer
--
À vélo, prendre une rue à contre-sens est moins dangeureux
que prendre un boulevard dans le sens légal. À qui la faute ?


Avatar
Nicolas George
DINH Viêt Hoà wrote in message :
avec UDP, tu utilises sendto() pour donner les port/addresse
destination.


En UDP, connect est possible également : il revient à fixer une destination
implicite pour les paquets envoyés avec send tout court, et à ignorer les
paquets qui ne viennent pas de l'adresse correspondante.

Avatar
Laurent Wacrenier
Thomas Nemeth écrit:
Maintenant il faudrait que j'étudie la possibilité de faire en sorte
que l'un des clients puisse contacter le serveur afin de le faire
changer de mode de fonctionnement. Je pense qu'un select dans un
autre thread permettrait de se mettre en attente de lecture...


Pas besoin de select() s'il y a des threads. Il suffit de bloquer sur
recvfrom() avec une socket de controle sur un autre port.

1 2 3 4 5