IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Communication socket UDP


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut Communication socket UDP
    Bonsoir, je souaiterais faire communiquer un Envoyeur et un Recepteur via ce que l'on va appeler un Intermediaire.

    Habituellement sans Intermediaire :
    L'Envoyeur est client, on a donc besoin de : une structure sockaddr_in pour le serveur, la remplir(nport,@,...), puis on peut enoyer/recevoir (sendto/recvfrom).
    Comment se fait-il qu'à aucun moment on(le client) dit sur quel port on recoit les trame?

    Le Recepteur est serveur, on a donc besoin : d'une structure addr_in pour soit et une pour le client, on remplie la sructure serveur, on bind, puis sendto/recvfrom.
    Idem, on renseigne rien sur le client. Pourquoi?

    Ensuite, admenttons que l'on ait un Intermediare qui prenne en argument : son_num_port @Receveur port_Receveur @Envoyeur port_Envoyeur

    Je n'arrive pas a communiquer dans les deux sens :
    Envoyeur ---> Intermediaire ---> Recepteur et
    Recepteur ---> Intermediare ---> Envoyeur

    Je précise que l'Intermediare gere tout cela, mais que c'est au niveau de l'Envoyeur et du Recepteur que je ne comprend pas comment faire.

    Car en definissant l'Envoyeur comme client(comme sité plus haut) et le Receveur comme serveur, je dois avoir comme configuration :
    ./intermediare 2000 localhost 3000 localhost 2000
    ./envoyeur 2000
    ./recepteur 3000

    Les numeros de port doivent etre identiques pour l'envoyeur et l'intermediare, mais le probleme est que cela ne marche que dans un seul sens : Envoyeur ---> Intermediare ---> Recepteur

    Je ne vois comment faire, jai essayé plusieurs formules (que je peux vous detailler) mais cela ne marche toujours pas.

    Merci de votre attention et de votre aide.

  2. #2
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Citation Envoyé par juve1897 Voir le message
    Comment se fait-il qu'à aucun moment on(le client) dit sur quel port on recoit les trame?
    La réponse est dans la norme :
    Citation Envoyé par http://www.opengroup.org/onlinepubs/009695399/functions/connect.html
    NAME

    connect - connect a socket

    SYNOPSIS

    #include <sys/socket.h>

    int connect(int socket, const struct sockaddr *address,
    socklen_t address_len);

    DESCRIPTION

    The connect() function shall attempt to make a connection on a socket. The function takes the following arguments:

    socket
    Specifies the file descriptor associated with the socket.
    address
    Points to a sockaddr structure containing the peer address. The length and format of the address depend on the address family of the socket.
    address_len
    Specifies the length of the sockaddr structure pointed to by the address argument.

    If the socket has not already been bound to a local address, connect() shall bind it to an address which, unless the socket's address family is AF_UNIX, is an unused local address.

  3. #3
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut
    Il s'agit de communications en mode UDP, donc non connecté, je ne pense pas que l'on doive utiliser de connect().

  4. #4
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par juve1897 Voir le message
    Bonsoir, je souaiterais faire communiquer un Envoyeur et un Recepteur via ce que l'on va appeler un Intermediaire.

    Habituellement sans Intermediaire :
    L'Envoyeur est client, on a donc besoin de : une structure sockaddr_in pour le serveur, la remplir(nport,@,...), puis on peut enoyer/recevoir (sendto/recvfrom).
    Comment se fait-il qu'à aucun moment on(le client) dit sur quel port on recoit les trame?
    Le port est choisi automatiquement. Si tu veux le spécifier explicitement, alors il te faut d'abord faire un bind sur ta socket client.

    Citation Envoyé par juve1897 Voir le message
    Le Recepteur est serveur, on a donc besoin : d'une structure addr_in pour soit et une pour le client, on remplie la sructure serveur, on bind, puis sendto/recvfrom.
    Idem, on renseigne rien sur le client. Pourquoi?
    Les informations seront données par le recvfrom. En effet, n'étant pas en mode connecté, n'importe qui peut émettre vers la socket UDP du serveur. recvfrom te diras qui a envoyé.

    Citation Envoyé par juve1897 Voir le message
    Ensuite, admenttons que l'on ait un Intermediare qui prenne en argument : son_num_port @Receveur port_Receveur @Envoyeur port_Envoyeur
    Soit tu laisse le choix des ports dynamiques mais ça impose qu'ils soient résolus lors du premier échange Client->Intermédiraire->Serveur.
    Soit tu forces tes 4 ports (client, intermédiaire_client, intermédiaire_serveur, serveur), et là tu passes par bind.
    Soit un mix.

  5. #5
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par juve1897 Voir le message
    Bonsoir, je souaiterais faire communiquer un Envoyeur et un Recepteur via ce que l'on va appeler un Intermediaire.

    Habituellement sans Intermediaire :
    L'Envoyeur est client, on a donc besoin de : une structure sockaddr_in pour le serveur, la remplir(nport,@,...), puis on peut enoyer/recevoir (sendto/recvfrom).
    Comment se fait-il qu'à aucun moment on(le client) dit sur quel port on recoit les trame?

    Le Recepteur est serveur, on a donc besoin : d'une structure addr_in pour soit et une pour le client, on remplie la sructure serveur, on bind, puis sendto/recvfrom.
    Idem, on renseigne rien sur le client. Pourquoi?
    Parce que que lors de l'émission de la commande par le client, le numéro de port source est transmis au destinataire. Il s'en sert ensuite automatiquement pour forger la réponse à condition d'utiliser le même sockaddr_in (les IP/PORT source et destination sont alors croisés).

    Comme il n'y a pas de connexion, le serveur ne connait pas le client à priori. Il ne peut donc pas initier le dialogue. Seul le client peut le faire.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Client                              Serveur
    sendto (..., sin)   -- Question --> recvfrom(..., sin)
    recvfrom (..., sin) <-- Réponse --  sendto (..., sin)
    Ensuite, admenttons que l'on ait un Intermediare qui prenne en argument : son_num_port @Receveur port_Receveur @Envoyeur port_Envoyeur

    Je n'arrive pas a communiquer dans les deux sens :
    Envoyeur ---> Intermediaire ---> Recepteur et
    Recepteur ---> Intermediare ---> Envoyeur

    Je précise que l'Intermediare gere tout cela, mais que c'est au niveau de l'Envoyeur et du Recepteur que je ne comprend pas comment faire.

    Car en definissant l'Envoyeur comme client(comme sité plus haut) et le Receveur comme serveur, je dois avoir comme configuration :
    ./intermediare 2000 localhost 3000 localhost 2000
    ./envoyeur 2000
    ./recepteur 3000

    Les numeros de port doivent etre identiques pour l'envoyeur et l'intermediare, mais le probleme est que cela ne marche que dans un seul sens : Envoyeur ---> Intermediare ---> Recepteur

    Je ne vois comment faire, jai essayé plusieurs formules (que je peux vous detailler) mais cela ne marche toujours pas.

    Merci de votre attention et de votre aide.
    Tu veux faire du routage de trame en UDP ? Je ne sais pas si c'est possible... Un routeur doit être à la fois client et serveur... C'est possible en TCP. Ou alors il faut faire du relayage de trame IP, donc sans se préoccuper du niveau 4 (UDP). Le noyau sait peut être faire ça. Ca doit dépendre du système...

    EDIT : Il semblerait qu'avec bind() sur un client, on puisse choisir le N° de port...

  6. #6
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut
    J'ai essayer avec bind(), mais voici le problème :
    Disons que j'ai fixé comme numéro de port :

    3333 pour l'intermédiaire(je rappele que l'on ne s'occupe pas de lui et qu'il est censé jouer son rôle a merveille)
    4444 pour le Recepteur
    5555 pour l'Envoyeur


    Dans l'Envoyeur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    ...
    struct sockaddr_in envoyeur, intermediaire;
    ...
    envoyeur.sin_family...
    envoyeur.si_addr...
    envoyeur.sin_port...
     
    intermediaire.sin_port = htons(3333); // j'essaye ainsi de forcé le numero de celui a qui je soihaite envoyer des trames
     
    ...
     
    if(bind(sockfd, (struct sockaddr *)&envoyeur, sizeof(envoyeur)) != 0)
        {
          perror("erreur lors de l'appel a bind -> ");
          exit(-2);
        }
    ...
     
    if(sendto(sockfd, frame[i], strlen(frame[i]), 0, (struct sockaddr *)&intermediaire, sizeof(intermediaire)) < 0)
        {
          perror("erreur a l'appel de la fonction sendto -> ");
          exit(-2);
        }
     
     
    if(recvfrom(sockfd, buf, 1024, 0,(struct sockaddr *)&intermediaire, &fromlen) < 0)
    	{
    		perror(" Receive from ");
    		exit(-1);
    	}
    ...
    Dans le Receveur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
     
     struct sockaddr_in my_addr; 
     struct sockaddr_in intermediaire;   
    ...
     
    /* idem*/
     
    intermediaire.sin_port = htons(3333);
     
    /* idem */
    Ensuite :
    ./envoyeur 5555
    ./receveur 4444
    ./intermediaire 3333 localhost 4444 localhost 5555

    Mais cela ne marche pas.

  7. #7
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Habituellement sans Intermediaire :
    L'Envoyeur est client, on a donc besoin de : une structure sockaddr_in pour le serveur, la remplir(nport,@,...), puis on peut enoyer/recevoir (sendto/recvfrom).
    Comment se fait-il qu'à aucun moment on(le client) dit sur quel port on recoit les trame ?
    On ne peut faire un recvfrom que sur un socket attaché à un port (c'est-à-dire grâce à bind) ou un socket placé en mode promiscuous (voir raw sockets ...) sinon effectivement comment la fonction saurait-elle sur quel port lire ...

    Le Recepteur est serveur, on a donc besoin : d'une structure addr_in pour soit et une pour le client, on remplie la sructure serveur, on bind, puis sendto/recvfrom.
    Idem, on renseigne rien sur le client. Pourquoi ?
    L'adresses source (l'adresse de l'envoyeur), le port source (port sur la machine émettrice depuis lequel les données ont été envoyées), ainsi que d'autres informations utiles sont contenues dans l'en-tête de chaque paquet circulant sur le réseau. Le récepteur connaît donc toujours l'expéditeur de n'importe quel paquet reçu.

    N'oublie pas non plus que si un socket n'a pas été à un port, à chaque appel de sendto, un port libre sera choisi pour envoyer les données. Sinon ce sera toujours le port sur lequel le socket est attaché.

    Ensuite, admenttons que l'on ait un Intermediare qui prenne en argument : son_num_port @Receveur port_Receveur @Envoyeur port_Envoyeur

    Je n'arrive pas a communiquer dans les deux sens :
    Envoyeur ---> Intermediaire ---> Recepteur et
    Recepteur ---> Intermediare ---> Envoyeur
    Dans ce cas, l'intermédiaire est le serveur et l'émetteur ainsi que le récepteur des clients.

    Le serveur écoute sur un port et s'il reçoit un message venant de l'émetteur, il transmet ce message au récepteur. Si le message vient du récepteur, il le transmettra à l'émetteur.

  8. #8
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut
    Citation Envoyé par Melem Voir le message
    Le serveur écoute sur un port et s'il reçoit un message venant de l'émetteur, il transmet ce message au récepteur. Si le message vient du récepteur, il le transmettra à l'émetteur.
    C'est exactement ce que je souhaite faire mais je n'y arrive pas.

    Car admettons que l'Intermediaire soit le serveur est l'Envoyeur le client1 et le receveur le client2, comment faire(en gros) pour que ca marche?

    Sachant que l'intermediaire a deja binder un socket pour chacun et qu'il envoi sur les ports fournis en parametre.
    Comment faire en sorte que les client(1 et 2) écoutent sur un port fixé(qui devra correspondre a celui fournit a l'intermediaire).
    C'est bien cela mon probleme.

  9. #9
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    On lance tout d'abord le serveur qui va écouter sur le port 5050 de la machine. Le serveur fait ensuite la boucle suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    while (!<condition d-arret>)
    {
        recvfrom(s, buffer, sizeof(buffer), 0, &from, &fromlen);
     
        if (<from.sin_addr.s_addr == "Addresse Client 1" && from.sin_port == "Port Client 1">)
        {
            <Ce message vient de Client 1, Transmettre a Client 2>
        }
        else if (<from.sin_addr.s_addr == "Addresse Client 2" && from.sin_port == "Port Client 2">)
        {
            <Ce message vient de Client 2, Transmettre a Client 1>
        }
    }
    Chaque client doit évidemment être attaché à un port ... Client 1 fait une boucle de de send (envoyer un message) suivi d'un recv (attendre une réponse) et Client 2 une boucle de recv (attendre un message) suivi d'un send (envoyer la réponse). C'est du half duplex, mais je te conseille de commencer par ça.

Discussions similaires

  1. Pb de socket udp
    Par phoenixia dans le forum MFC
    Réponses: 7
    Dernier message: 01/06/2006, 17h08
  2. [socket UDP] Codage BER : Format des Tag (TLG)
    Par Lolita59 dans le forum Réseau
    Réponses: 28
    Dernier message: 19/05/2006, 17h37
  3. Socket : UDP ou TCP
    Par lafracas dans le forum Développement
    Réponses: 2
    Dernier message: 10/04/2006, 22h43
  4. code c pour sockets (udp vers tcp et inversement)
    Par HiT dans le forum Développement
    Réponses: 11
    Dernier message: 19/11/2005, 18h03
  5. Notion sur Socket UDP
    Par oxor3 dans le forum Développement
    Réponses: 3
    Dernier message: 05/04/2004, 00h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo