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

C++ Discussion :

[Réseau] Winsock 2 ; configuration d'un port source


Sujet :

C++

  1. #1
    Candidat au Club
    Inscrit en
    Septembre 2008
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 9
    Points : 4
    Points
    4
    Par défaut [Réseau] Winsock 2 ; configuration d'un port source
    Bonjour a tous,
    le probleme est le suivant: j'envoie des paquets par UDP a une machine sur un port de destination donne a partir d'un port aleatoirement attribue.
    Je cherche simplement la fonction me permettant de fixer le port source (j'ai effectue pas mal de recherches mais tres peu de resultats sont apparus, la seule "solution" que j'ai trouve (sur ce site mais en section c#) c'est de faire un bind de la socket sur le port, mais cela ne fonctionne pas).
    Je bosse avec Winsock 2

    Merci d'avance

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Il me semble que faire un bind de la socket sur le port est LA solution pour ça...
    En quoi cela ne marche-t-il pas exactement ?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Candidat au Club
    Inscrit en
    Septembre 2008
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 9
    Points : 4
    Points
    4
    Par défaut
    Merci pour la reponse. En fait cela ne fonctionne pas dans la mesure ou le port source est toujours aleatoire =/
    La situation n'a pas evolue avec cette fonction en fait.

  4. #4
    Candidat au Club
    Inscrit en
    Septembre 2008
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 9
    Points : 4
    Points
    4
    Par défaut
    voici le code :

    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
     
    void DLL_EXPORT sendMulticast(unsigned char *send_str, int send_len, int type, int port, char *group)
    {
        int             sock;                   /* socket descriptor */
        struct          sockaddr_in mc_addr;    /* socket address structure */
        char            *mc_addr_str;           /* multicast IP address */
        unsigned short  mc_port;                /* multicast port */
        unsigned char   mc_ttl=1;               /* time to live (hop count) */
     
        mc_addr_str = group;        /* arg 1: multicast IP address */
        mc_port     = port;         /* arg 2: multicast port number */
     
        /* create a socket for sending to the multicast address */
        sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
     
        /* set the TTL (time to live/hop count) for the send */
        setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*) &mc_ttl, sizeof(mc_ttl));
     
        /* construct a multicast address structure */
        memset(&mc_addr, 0, sizeof(mc_addr));
        mc_addr.sin_family      = AF_INET;
        mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
        mc_addr.sin_port        = htons(mc_port);
        bind(sock, (SOCKADDR*) &mc_addr, sizeof(mc_addr));
     
        sendto(sock, (char *)send_str, send_len, 0, (struct sockaddr *) &mc_addr, sizeof(mc_addr));
     
        closesocket(sock);
    }
    WSAStartup a ete utilise avant l'appel de cette fonction, la dll est donc bien chargee.

  5. #5
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Points : 50 367
    Points
    50 367
    Par défaut
    Il te faut 2 structures sockaddr_in

    1 pour décrire le destinataire (tu l'as déjà faite)
    1 pour décrire le bind de ton socket en local. et dans celle là, je pense qu'il faut initialiser le membre ".sin_addr.s_addr" = avec la valeur INETADDR_ANY
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  6. #6
    Candidat au Club
    Inscrit en
    Septembre 2008
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 9
    Points : 4
    Points
    4
    Par défaut
    Je viens de tenter avec une nouvelle structure initialisee de la meme maniere que la premiere, cependant ca ne fonctionne toujours pas.
    pour la premiere il me dit a la compilation : "error: `INETADDR_ANY' was not declared in this scope"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    mc_addr2.sin_addr.s_addr = htonl(INETADDR_ANY);
    j'ai egalement essaye :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    mc_addr2.sin_addr.s_addr = htonl(INADDR_ANY);
    Mon IDE est code::blocks.
    J'utilise le compilateur mingw32-g++.

  7. #7
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Utilises 0 !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    #define INADDR_ANY              (ULONG)0x00000000
    Mais bon... c'est étonnant qu'il ne soit pas défini... c'est quand même la base des winsocks
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  8. #8
    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
    Points : 13 017
    Points
    13 017
    Par défaut
    Quelque chose de ce gout là:
    -> gethostname pour retrouver ton adresse locale sous forme de nom
    -> gethostbyname pour retrouver ton adresse IP
    -> bind sur cette adresse avec le port UDP
    -> sendto sur l'adresse + port destinataire.
    Les deux premiers peuvent aussi être remplacé par l'utilisation de 127.0.0.1 comme adresse locale.

  9. #9
    Candidat au Club
    Inscrit en
    Septembre 2008
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 9
    Points : 4
    Points
    4
    Par défaut
    @nicroman : INADDR_ANY etait bien defini lui, mais j'ai quand meme tente de le definir sous un autre nom pour l'essayer, mais ca n'a pas fonctionne

    @3DArchi : j'ai tente ces etapes, mais le probleme est toujours le meme

    Je vais le reexpliquer au cas ou je me sois mal exprime ce qui vous aurait oriente vers une fausse piste (on ne sait jamais, et moi encore moins ) :

    j'envoie des paquets a partir d'un port X, vers le port A d'un destinataire. Celui-ci le recoit. Il me repond en m'envoyant un paquet a partir du port A, vers le port X de mon pc.
    Le probleme c'est que le port X est aleatoire, or j'aimerais prevoir le port utilise pour etre capable de recevoir le paquet envoye en reponse par ma cible. Mon but ici est donc de figer le port X pour savoir ou recevoir les paquets (je n'ai pas acces au soft de la cible pour forcer le port de destination).

    J'utilise le protocole UDP, la communication se fait a travers le multicast (les machines triant les paquets qui leur sont destines).
    La librairie utilisee est Winsock2, mon IDE Code::Blocks, mon compilateur mingw32-g++.
    Le produit de la compilation est une DLL utilisee par un programme dans un autre langage (ca n'a pas d'importance ici, du moins j'en doute).

    Je vous dit pour les reponses qui ont deja ete donnees.

  10. #10
    Candidat au Club
    Inscrit en
    Septembre 2008
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 9
    Points : 4
    Points
    4
    Par défaut
    Eureka!

    C'est assez "idiot", en fait il y a une information que je ne vous ai pas donne (ca m'est completement sorti de la tete, comme quoi on ne se relit jamais assez) : une autre socket utilise ce port, pour traiter les paquets entrants. Cette socket possede l'option SO_REUSEADDR, pour que l'adresse puisse etre reutilisee. Cependant, pour que la socket d'envoi puisse etre bind sur le meme port, elle doit elle-meme etre parametree avec cette option.

    Voici le code pour ceux que ca interresserait :
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    void DLL_EXPORT sendMulticast(unsigned char *send_str, int send_len, int type, int port, char *group)
    {
        int             sock;                   /* socket descriptor */
        struct          sockaddr_in mc_addr;    /* socket address structure */
        struct          sockaddr_in mc_addr2;   /* socket bind structure */
        char            *mc_addr_str;           /* multicast IP address */
        unsigned short  mc_port;                /* multicast port */
        unsigned char   mc_ttl=1;               /* time to live (hop count) */
     
        mc_addr_str = group;        /* arg 1: multicast IP address */
        mc_port     = port;         /* arg 2: multicast port number */
     
        /* create a socket for sending to the multicast address */
        sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
     
        /* set the TTL (time to live/hop count) for the send */
        setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (char*) &mc_ttl, sizeof(mc_ttl));
     
        int flag_on = 1;            /* socket option flag */
        /* Make the socket reusable,
        any other socket must be set with this option if they use the same port */
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&flag_on, sizeof(flag_on));
     
        /* construct a multicast address structure */
        memset(&mc_addr, 0, sizeof(mc_addr));
        mc_addr.sin_family      = AF_INET;
        mc_addr.sin_addr.s_addr = inet_addr(mc_addr_str);
        mc_addr.sin_port        = htons(mc_port);
     
        /* construct socket bind structure*/
        memset(&mc_addr2, 0, sizeof(mc_addr));
        mc_addr2.sin_family      = AF_INET;
        mc_addr2.sin_addr.s_addr = htons(INADDR_ANY);
        mc_addr2.sin_port        = htons(mc_port);
        /* bind the port in order to set the source port */
        bind(sock, (SOCKADDR*) &mc_addr2, sizeof(mc_addr2));
     
        /* send to the multicast group "group" on the port "port" from the port "port" */
        sendto(sock, (char *)send_str, send_len, 0, (struct sockaddr *) &mc_addr, sizeof(mc_addr));
     
        /* close the socket */
        closesocket(sock);
    }
    Je vous remercie pour votre participation, et pour les solutions que vous m'avez apporte !
    Vive developpez !

  11. #11
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Forcément... si on a que la moitié du probleme, et que tu nous dis pas que ca foirait à l'execution avec une erreur "address already in use" !!!! ...

    Moi j'étais resté sur le problême de compilation

    Sinon.... tu n'as pas besoin de fixer le port X d'origine... tu l'as à la reception dans le paquet... (ca te permettra en plus de passer le port-masquerading éventuels).


    Genre:
    A envoit un paquet (port 'libre' Ax) à B sur le port Bx (fixé lui).
    B recoit le paquet, et, dans l'addresse d'origine a bien A,Ax ....

    Si il y a du NAT entre les deux, tu recevra bien C,Cx qu'il faut utiliser pour toucher A,Ax !
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  12. #12
    Candidat au Club
    Inscrit en
    Septembre 2008
    Messages
    9
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 9
    Points : 4
    Points
    4
    Par défaut
    tu n'as pas besoin de fixer le port X d'origine... tu l'as à la reception dans le paquet
    Le probleme c'est que je suis le premier a envoyer le paquet, je n'ai donc aucune info a la base, c'est a moi de definir tout ca.

    Je debute dans le reseau (ca fait meme pas un mois que j'ai commence), et c'est pas super simple, d'ailleurs j'ai du relire plusieurs fois ce que tu as explique (j'ai meme sollicite google)

    Merci pour l'aide!

  13. #13
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Dans toute application client-serveur, il faut, à un moment donné avoir une adresse fixe.
    Quand je parle d'adresse, j'entends adresse du protocol, c'est à dire un couple IP/port pour le protocol UDP ou TCP.
    Et bien sur, ca peut être une adresse multicast voir broadcast (pour toucher toutes les machines sur le réseau local).

    Disons que S est cette adresse fixe.

    Maintenant, j'ai un client qui veut accéder à S... Le client va donc créer une adresse "locale" C (ou bien statiquement avec 'bind' ou bien automatiquement, sans 'bind') et accéder à S ('sendto(S,data)').

    Quand S va recevoir le paquet UDP, il va faire: 'recvfrom(?,data)' et recevra donc une adresse.
    Dans les cas simples (même réseau local, adresses IP publiques) cette adresse sera C... mais pas toujours....
    Dans les cas classiques (serveur et client sur des réseaux locaux différents, et utilisant des adressages privés) l'adresse sera D !!
    Car entre C et S, un appareil de routage s'amusera à modifier l'adresse d'origine du paquet en "D"... (ce qu'on appelle le PAT/NAT), et le seul moyen de remonter à C c'est de communiquer avec cette adresse D.

    Utiliser un port fixe pour un 'client' est donc non seulement dangereux, mais *tres* compliqué parceque nécessitant de mettre en place des règles de routage.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 13/08/2007, 09h47
  2. [réseau] capter une requête sur un port spécifique
    Par ebaynaud dans le forum Langage
    Réponses: 1
    Dernier message: 29/09/2006, 13h26
  3. [Réseau local] Impossible d'ouvrir un port!
    Par webrider dans le forum Hardware
    Réponses: 3
    Dernier message: 10/08/2006, 08h51
  4. Configurer APACHE malgré PORT 80 fermé ?
    Par Sparkle dans le forum Apache
    Réponses: 2
    Dernier message: 20/07/2006, 13h15
  5. configuration d'un port PCI
    Par ptifleure dans le forum MFC
    Réponses: 2
    Dernier message: 11/04/2006, 10h08

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