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 :

Fonction WSARecvFrom fail..


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Points : 18
    Points
    18
    Par défaut Fonction WSARecvFrom fail..
    Bonjour,

    Je développe un serveur UDP en utilisant les fonctions WSA* de la lib winsock.

    Après avoir créer la socket (WSASocket) et la binder comme il faut, je suis face à un problème concernant la fonction WSARecvFrom, voici son implémentation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    WSARecvFrom(
                        sock_,
                        &dataBuff,
                        1,
                        &bytesRecv,
                        &flags,
                        (SOCKADDR *)&senderAddr,
                        &senderAddrSize,
                        &overLapped,
                        NULL
                       );
    Le problème vient de la valeur de retour, j'obtiens constamment le code erreur WSAENOBUFS (10055) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    No buffer space available.
    An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.
    Or, je pense avoir bien déclaré le buffer de réception (dataBuff) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    WSABUF dataBuff;
    const int buffLen = DATA_SIZE;
    char buff[DATA_SIZE];
     
    dataBuff.len = buffLen;
    dataBuff.buf = buff;
    J'ai lu quelque part que cette erreur apparaissait si le port bindé dépassé la valeur 5000 mais j'utilise le port 1234 et même résultat...

    Merci pour votre patience et de l'aide que vous pourrez m'apporter.

  2. #2
    Membre averti Avatar de niglo
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 379
    Points : 383
    Points
    383
    Par défaut
    Hello,

    ce que je comprends de ton message d'erreur, c'est que ton buffer n'est pas assez grand pour recevoir les données.

    Que vaut DATA_SIZE ?

    ++

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    DATA_SIZE est une macro perso, elle vaut 1024, mais la fonction plante avant même une quelconque réception de données...

  4. #4
    Membre averti Avatar de niglo
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 379
    Points : 383
    Points
    383
    Par défaut
    d'après la MSDN, le problème vient du numéro de port de ton socket :
    http://support.microsoft.com/kb/196271/fr

    Comment sont déclarés senderAddr et sock_ ?

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Une petite info au passage : la bibliothèque winsock n'est pas portable (c'est une bibliothèque "made by microsoft" )

    Tu me diras sans doute que tu n'en as rien à foutre, mais il se fait qu'il existe une excellente bibliothèque qui permet de gérer les socket (TCP et UDP) de manière transparente et portable pour l'utilisateur, et ce, quel que soit le système pour lequel l'application sera compilée.

    Ce n'est pas le moindre intérêt de cette bibliothèque, car elle rend la gestion et l'utilisation des sockets, ports et autres protocoles liés à la transmission des données par le net bien plus faciles . j'ai nommé boost asio !

    Alors, oui, je sais... Tu vas me rétorquer que l'utilisation de cette bibliothèque te fait penser au fait d'utiliser un bazooka pour tuer une mouche, que tu n'as pas envie d'installer tout boost "uniquement" pour cela, ou encore me trouver plein d'autres faux prétextes pour ne pas suivre ce conseil.

    Et pourtant, je peux t'assurer que tu gagnera énormément tant en terme de facilité d'utilisation, qu'en terme de temps de développement ou qu'en terme de portabilité, et qu'il serait donc vraiment dommage de s'en priver
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par niglo Voir le message
    d'après la MSDN, le problème vient du numéro de port de ton socket :
    http://support.microsoft.com/kb/196271/fr

    Comment sont déclarés senderAddr et sock_ ?
    Je ne pense pas que cela vienne du numéro de port (j'ai testé avec beaucoup de valeurs différentes),
    sinon pour les déclarations :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    struct sockaddr_in senderAddr;
    SOCKET sock_;
    pour répondre a koala1 :
    on m'impose l'utilisation des fonctions WSA* ! je n'ai pas le choix

    La question de portabilité n'est pas un problème, le tout est abstrait et encapsulé. Je jongle entre deux objets version WIN32 et UNIX (avec les macros #ifdef #endif); du coup mon serveur est utilisable sous Windows et Unix.
    Au passage, ma version UNIX fonctionne parfaitement...

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par ouhare Voir le message
    pour répondre a koala1 :
    on m'impose l'utilisation des fonctions WSA* ! je n'ai pas le choix

    La question de portabilité n'est pas un problème, le tout est abstrait et encapsulé. Je jongle entre deux objets version WIN32 et UNIX (avec les macros #ifdef #endif); du coup mon serveur est utilisable sous Windows et Unix.
    Au passage, ma version UNIX fonctionne parfaitement...
    Mea culpa... j'ai oublié de préciser : c'est exactement ce que fait boost asio, en t'évitant de devoir réinventer la roue

    Maintenant, si c'est pour un TP... Mais penses à asio le jour où tu seras dans une situation similaire à titre privé (ou professionnel)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Membre averti Avatar de niglo
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 379
    Points : 383
    Points
    383
    Par défaut
    Peux-tu également montrer comment tu renseignes sock_ et senderAddr ?

    Sinon, plusieurs choses à vérifier :

    Winsock correctement initialisé ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
        if (rc != 0) {
            /* Could not find a usable Winsock DLL */
            wprintf(L"WSAStartup failed with error: %ld\n", rc);
            return 1;
        }
    socket bien crée ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        RecvSocket = WSASocket(AF_INET,
                               SOCK_DGRAM,
                               IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
     
        if (RecvSocket == INVALID_SOCKET) {
            /* Could not open a socket */
            wprintf(L"WSASocket failed with error: %ld\n", WSAGetLastError());
            WSACloseEvent(Overlapped.hEvent);
            WSACleanup();
            return 1;
        }
    socket bien lié ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        rc = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));
        if (rc != 0) {
            /* Bind to the socket failed */
            wprintf(L"bind failed with error: %ld\n", WSAGetLastError());
            WSACloseEvent(Overlapped.hEvent);
            closesocket(RecvSocket);
            WSACleanup();
            return 1;
        }

  9. #9
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    [hors-sujet]

    Citation Envoyé par ouhare Voir le message
    Je jongle entre deux objets version WIN32 et UNIX (avec les macros #ifdef #endif);
    Miam miam la portabilité à coup de pré processeur. Je crois que je vais écrire un petit article sur le sujet pour en finir avec ces mauvaises habitudes ^^

    [/hors-sujet]
    Find me on github

  10. #10
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    [hors-sujet]



    Miam miam la portabilité à coup de pré processeur. Je crois que je vais écrire un petit article sur le sujet pour en finir avec ces mauvaises habitudes ^^

    [/hors-sujet]
    que veux-tu dire par Miam miam?

    J'utilise deux objets qui implémentent la même interface, la création de l'objet se fait entre ces deux directives, mais les appels de méthodes sont les mêmes !

    Je trouve ca plutot efficace et plutot propre.. on m'aurait menti?

    @niglo:

    Je me suis inspiré aussi du code trouvé sur la MSDN, donc mon code est quasiment le même que celui que tu proposes.. mise à part les messages d'erreur que je redirige sur std::cerr.

  11. #11
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par ouhare Voir le message
    J'utilise deux objets qui implémentent la même interface, la création de l'objet se fait entre ces deux directives, mais les appels de méthodes sont les mêmes !

    Je trouve ca plutot efficace et plutot propre.. on m'aurait menti?
    Je résume rapidement car ce n'est pas le sujet du post, mais la bonne manière consiste à écrire deux implémentations (*.cpp) du même (*.h), et de faire sélectionner à la chaîne de compilation le bon fichier *.cpp en fonction de la plateforme. Alors que là tu dois te coltiner une classe mère pour rien. On peut en rediscuter en MP ou sur un autre post.
    Find me on github

  12. #12
    Membre averti Avatar de niglo
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 379
    Points : 383
    Points
    383
    Par défaut
    Citation Envoyé par ouhare Voir le message
    @niglo:
    Je me suis inspiré aussi du code trouvé sur la MSDN, donc mon code est quasiment le même que celui que tu proposes.. mise à part les messages d'erreur que je redirige sur std::cerr.
    OK, parfait, c'était au cas où.

    Peux-tu mettre un peu plus de code de ce que tu fais autour du WSARecvFrom ?
    Et aussi (juste pour être sûr) les affectations d'@ IP et port de ton socket ?

    Une autre piste : est-ce que tu as vérifié que le port était ouvert sur ton firewall ?

  13. #13
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Mars 2009
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    bon, j'ai trouvé une solution, apparemment cela venait de la structure WSAOVERLAPPED, (avant dernier paramètre de WSARecvFrom)....

    J'ai testé en remplacant la structure par NULL et ho miracle !
    tout fonctionne !
    au passage, je n'ai toujours pas vraiment saisi l'utilité de cette structure...
    d'ailleurs le code erreur que la fonction me renvoyait me laisse encore dans le flou...
    enfin je pense que pour mon cas, je n'en est pas vraiment l'utilité.

    merci encore niglo de t’être penché sur mon problème !

  14. #14
    Membre averti Avatar de niglo
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    379
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Bas Rhin (Alsace)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 379
    Points : 383
    Points
    383
    Par défaut
    pas de soucis, si je peux aider !

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 01/09/2009, 07h38
  2. Réponses: 0
    Dernier message: 27/07/2009, 23h21
  3. Réponses: 7
    Dernier message: 26/02/2008, 14h08
  4. CDataExchange ; fonction fail
    Par Seth77 dans le forum MFC
    Réponses: 4
    Dernier message: 08/07/2007, 14h26
  5. Fonction 'failed' avec comme paramètre un HResult
    Par Leobaillard dans le forum Delphi
    Réponses: 1
    Dernier message: 08/08/2006, 20h29

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