begin process at 2012 02 11 14:20:13
  Trouver un code source :
 
dans
 
Accueil > Forum > 

C++ & C++ .NET

 > 

Windows

 > 

Réseau & Internet

 > 

problème avec WSAGetLastError()


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

problème avec WSAGetLastError()

samedi 1 juillet 2006 à 04:13:10 | problème avec WSAGetLastError()

fredo2009

Bonjour @ tous

Je suis en train de coder un scanner multithread avec socket non bloquant.
Mon soucis est de récupérer le message d'erreur résultant du connect: si la connexion a réussi ou bien si elle a été refusée ou bien fermer le socket qd le timeout est dépassé.

En mode bloquant , je récupère bien le GetLastError() mais je ne peux pas régler le timeout du socket:
if(connect(mysock,(struct sockaddr *) & server,sizeof(server))!=0)
  {
  code=GetLastError();

  if(code==10061)
  {printf("la connexion sur le port %d a ete refusee \n",port);}

  }
    else
    {
    printf("la connexion sur le port %d a reussie\n",port);
    }

en mode non bloquant, select me renvoie la même erreur 0 pour le time out dépassé et la connexion refusée. Et pour la connexion réussie je reçois l'erreur 10035.

[code]connect(conf->sock, (SOCKADDR *)&(conf->sin), sizeof(conf->sin));

          int codeRetour = select(0,&socketToCheck,&socketToCheck,&socketToCheck,&tempo);

                    conf->code=GetLastError();
                    if (conf->code==10061)
                    {
                    printf("la connexion sur le port %d a ete refusee \n",port);                     
                    closesocket(conf->sock);                       
                    shutdown(conf->sock,2); 
                    }
                    else 
                    {
                    printf("la connexion sur le port %d a reussie\n",port);            
                    closesocket(conf->sock);                       
                    shutdown(conf->sock,2); 
                    }
[/code]

samedi 1 juillet 2006 à 21:00:36 | Re : problème avec WSAGetLastError()

excrt

tu ne peux pas envoyer le même « fd_set » aux trois « fd_set » que select() attent.
select() modifie les « fd_set » qu'il recoit. en passant, toi tu utilises « GetLastError() » et non « WSAGetLastError() »

//fd_set fdsread; // inutile pour un connect()
fd_set fdswrite;
fd_set fdserror;
timeval timeout;
int retval;
unsigned long noblock = 1;

//ref::http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/ioctlsocket_2.asp
    ioctlsocket(conf->sock, FIONBIO, &noblock);

    // initialize les  « fd_set »
    FD_ZERO(&fdswrite);
    FD_ZERO(&fdserror);

    // ajoute notre socket
    FD_SET(conf->sock, &fdswrite);
    FD_SET(conf->sock, &fdserror);

    // le timeout
    timeout.tv_sec = X;
    timeout.tv_msec = Y;

    // connect( ... );

ref::http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/select_2.asp
    retval = select(0, NULL, &fdswrite, &fdserror, &timeout);

    if (retval > 0)
    {
        if ( FD_ISSET(conf->sock, &fdswrite) ) {
            // ready
        }
        else if ( FD_ISSET(conf->sock, &fdserror) ) {
            printf("socket error: %d\n", WSAGetLastError());
        }
    }
    else if (retval == 0) {
        puts("timeout");
    }
    else if (retval == SOCKET_ERROR) {
        printf("select() error: %d\n", WSAGetLastError());
    }

pour les codes/messages d'erreurs:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/system_error_codes.asp


-=-= ExCRT =-=-
lundi 3 juillet 2006 à 03:03:40 | Re : problème avec WSAGetLastError()

fredo2009

C vrai que c plus propre comme ça.
Mais le résultat n'est pas encore correct.

Par ex je devrais obtenir qque chose comme ceci:

port 110 occupe  WSAGetLastError = 0 //la connexion a reussie sur ce port
port 111 ferme WSAGetLastError = 10060 //timeout
port 112 ferme WSAGetLastError = 10060 //timeout
port 113 libre WSAGetLastError = 10061 //la connexion a ete expressement refusee

Et au lieu de ça j'obtiens:
port 110 occupe WSAGetLastError = 10035
port 111 timeout WSAGetLastError = 0
port 112 timeout WSAGetLastError = 0
port 113 libre WSAGetLastError = 0
port 114 timeout WSAGetLastError = 0
port 115 timeout WSAGetLastError = 0
port 116 select() error = 10038
port 117 timeout WSAGetLastError = 0
port 141 select() error =  10038

Je n'ai donc pas les messages d'erreur attendu.
De plus le code erreur 10038 arrive aléatoirement. Je peux scanner 2 fois le même port, il ne sortira pas à chaque fois cette erreur.
Et si j'augmente le nbre de thread à plus de 9, le port 113 apparait en timeout.

Voilà le code complet :

#include "winsock2.h"
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "ws2_32.lib")
#include <time.h>
#include "String.h"
#include <winbase.h>

struct config
 {
 int sock;
 sockaddr_in sin;
 int ip;
 int port;
 int code;
 HANDLE hthread;
 MSG msg;
 FILE * fic; //pour enregistrer ds un fichier les résultats. Qd le code sera au point ^^
 };

DWORD WINAPI connection( LPVOID Param )
 {
 struct config * conf = (struct config *)Param;
 WSADATA WSAData;
 WSAStartup(MAKEWORD(2,2), &WSAData);
 conf->sock = socket(PF_INET,SOCK_STREAM,0);
 conf->sin.sin_addr.s_addr = ntohl(conf->ip);
 conf->sin.sin_family = AF_INET;
 conf->sin.sin_port = ntohs(conf->port);
   
          //Passage de la socket en mode non bloquant
          unsigned long optVal=1;
          ioctlsocket(conf->sock,FIONBIO,&optVal);
      
          //fd_set fdsread; // inutile pour un connect()
          fd_set fdswrite;
          fd_set fdserror;

          timeval tempo;
          tempo.tv_sec = 2; //en s
          tempo.tv_usec = 0; //en ms
          // initialize les  « fd_set »
          FD_ZERO(&fdswrite);
          FD_ZERO(&fdserror);
          // ajoute notre socket
          FD_SET(conf->sock, &fdswrite);
          FD_SET(conf->sock, &fdserror);
         
          connect(conf->sock, (SOCKADDR *)&(conf->sin), sizeof(conf->sin));

    int retval = select(0, NULL, &fdswrite, &fdserror, &tempo);
    if (retval > 0)
    {
        if ( FD_ISSET(conf->sock, &fdswrite) )
        {
         printf ("port %d occupe WSAGetLastError %d\n",conf->port, WSAGetLastError()); 
            // ready
        }
        else if ( FD_ISSET(conf->sock, &fdserror) ) {
            printf("port %d libre WSAGetLastError %d\n",conf->port, WSAGetLastError());
        }
    }
    else if (retval == 0) {
        printf("port %d timeout WSAGetLastError %d\n",conf->port,WSAGetLastError());
    }
    else if (retval == SOCKET_ERROR) {
         //if (WSAGetLastError()!=10038)
        {
            printf("port %d select() error: %d\n",conf->port, WSAGetLastError());
        }
    }
              //on repasse en mode bloquant
              optVal = 0;
              ioctlsocket (conf->sock, FIONBIO, &optVal);
   
    shutdown(conf->sock,2);
    closesocket(conf->sock);
 WSACleanup();
 free(conf);
 return 0;
 }
   
int main(int argc, char *argv[])
 {
 if ( argc == 4)
    { 
       struct config * conf = NULL;
       int nbrethread;
       int nthread;
       int portascanner;
       int scanip;
       portascanner = atoi(argv[1]);
    nbrethread = atoi(argv[2]);
    scanip = htonl(inet_addr(argv[3]));
       SetTimer(NULL,NULL,2000,NULL);
         for (;;)
   {  
             nthread = nbrethread;
               
                for (;nthread>0;nthread--)
    {
                conf = (struct config *) malloc(sizeof(struct config) );
                conf->ip = scanip;
                conf->port=portascanner;
    conf->hthread = CreateThread(NULL, 0, &connection, conf, 0, 0);
    CloseHandle(conf->hthread);
    portascanner++;
    }
    
    //ptite tempo de 2s entre chaque série de thread
                GetMessage(&conf->msg,NULL,0,0);
                while (conf->msg.message!=WM_TIMER)
                {;;}
                CloseHandle(conf->hthread);
   }
    KillTimer(NULL,NULL);
       return 0;
     }
 else
  {
  printf("Usage : scan.exe port_debut nthread ip\n");
  return 0;
 
  }
 }


 

lundi 3 juillet 2006 à 16:59:47 | Re : problème avec WSAGetLastError()

excrt

WSAStartup() tu dois l'appeler « une fois par _Process_ », pas par thread ...

int main()
{
    // ...
    WSAStartup(..., ...);

    // ...

    WSACleanup();
    return 0;
}

après l'appel a select(), si ton socket est présent dans « fdswrite » c'est qu'il est pret pour l'envoie de données, donc, connexion réussi, pas d'échec. s'il est présent dans fdserror c'est qu'il y a erreur, donc la connexion a probablement échouée ...

tu peux récupérer le code d'erreur associé a chacun des sockets via « getsockopt() »

int getSocketError(SOCKET sock)
{
    int error_code;
    int size = sizeof(int);

    if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &error_code, &size) != SOCKET_ERROR) {
        return error_code;
    }
    return WSAGetLastError();
}

    if ( FD_ISSET(conf->sock, &fdserror) ) {
        printf("socket error %d\n", getSocketError(conf->sock));
    }

pour tes « include »

#pragma comment(lib, "ws2_32.lib") // fait gaffe, ce « #pragma » ne fonctionne qu'en C++(tu compile en C++ présentement, va dans la config et change ca pour une compilation en C)
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

//#include <winbase.h> // <winsock2.h> inclut <windows.h> qui lui inclut <winbase.h> et d'autres fichiers

ton main() est ... bizarre ...

int main(int argc, char *argv[])
 {
 if ( argc == 4)
    { 
       struct config * conf = NULL;
       int nbrethread;
       int nthread;
       int portascanner;
       int scanip;
       portascanner = atoi(argv[1]);
    nbrethread = atoi(argv[2]);
    scanip = htonl(inet_addr(argv[3]));
       SetTimer(NULL,NULL,2000,NULL); // why?
         for (;;)
   {  
             nthread = nbrethread;
               
                for (;nthread>0;nthread--)
    {
                // ici, tu as un malloc() mais sans free() plus bas ... Problème!
                // c'est dans ton main() que tu devrais faire appel a free()
                // et non dans le thread
                conf = (struct config *) malloc(sizeof(struct config) );
                conf->ip = scanip;
                conf->port=portascanner;
    conf->hthread = CreateThread(NULL, 0, &connection, conf, 0, 0);
    CloseHandle(conf->hthread); // pourquoi fermes-tu le thread immédiatement après l'avoir créé???
    portascanner++;
    }
   
    // Ca ce n'est pas bon, mais pas du tout ...

    //ptite tempo de 2s entre chaque série de thread
                //GetMessage(&conf->msg,NULL,0,0);
                // si « conf->msg.message » ne vaut pas WM_TIMER
                // tu boucleras infiniment
                //while (conf->msg.message!=WM_TIMER)
                //{;;}
                while (GetMessage(&(conf->msg), NULL, 0, 0))
                {
                    if (conf->msg.message == WM_TIMER) {
                        break;
                    }
                }
                CloseHandle(conf->hthread);
                free(conf); // <<==
   }
    KillTimer(NULL,NULL);
       //return 0;
     }
 else
  {
  printf("Usage : scan.exe port_debut nthread ip\n");
  //return 0;
   }
   return 0;
 }

pourquoi utilises-tu SetTimer()/GetMessage()/etc.? si tu veux faire une pause de X [milli]sec, utilise « VOID Sleep(DWORD dwMilliSec); »

Sleep( 2000 ); // aussi simple que ca ..

si tu veux lancer plusieurs threads avec différentes informations(struct config), utilise ceci:

#define MAX_THREAD  MAXIMUM_WAIT_OBJECTS

    HANDLE hThreads[MAX_THREAD];
    struct config* confs = (struct config*)malloc(MAX_THREAD * sizeof(struct config));

    for (i = 0; i < MAX_THREAD; i++)
    {
        confs[i].x = x_value;
        confs[i].y = y_value;
        confs[i].z = z_value;
        // etc.

        hThreads[i] = CreateThread(NULL, 0, connection, &(confs[i]), 0, 0);
    }

    // on attend les threads
    WaitForMultipleObjects(MAX_THREAD, hThreads, TRUE, INFINITE);

    // fin des threads
    free(confs);

etc.
etc.
etc.

-=-= ExCRT =-=-
mercredi 5 juillet 2006 à 09:49:59 | Re : problème avec WSAGetLastError()

fredo2009

Merci excrt , c vraiment un cours que tu m'as fait là.

pourquoi utilises-tu SetTimer()/GetMessage()/etc.?
j'avais commencé par un Sleep(2000) et puis j'ai lu sur qques forum que Sleep avait tendance à endorpmir tous le programme. J'ai donc cherché autre chose pour faire une tempo. Mais finalement ça n change rien, je remet donc le Sleep.

#pragma comment(lib, "ws2_32.lib") // fait gaffe, ce « #pragma ».....
En fait ce pragma ne me sert à rien vu que je compile sous dev. Il me suffit de rajouter ds l'editeur de lien -lwsock32. D'après ce que j'ai compris il aurait servi pour une compilation sous visual.

Enfin le prog commence à tourner un peu plus rond. Il fonctionne sans bug jusqu'à 10 thread simultannés. Au-delà, il ne détecte plus les connexions refusées mais seulement les connexions réussies.



Cette discussion est classée dans : port, code, connexion, sock, conf


Répondre à ce message

Sujets en rapport avec ce message

socket 100% CPU [ par fredo2009 ] Salut@tousVoilà la fonction que j'utilise pour savoir si un port est ouvert sur une ip:DWORD WINAPI connection( LPVOID Param ) { struct config * conf pb pr écouter sur un port... [ par Gendal67 ] Bonsoir all...J'avais envie de créer une application utilisant les sockets liées à une connection TCP/IP qui écoute sur un port précis. Jusque là, pas [FTP] Schema de fonctionnement [ par ZedMaTrix ] Bonjours à tous !Bon je me fais ma petite classe FTP donc, et là je bloque un peu sur les commandes PORT et PASV.Y a un moment j'avais déjà tout codé Erreur compilation, Requette pour Connaitre le premier port ouvert..... [ par wizard512 ] Bonsoir,Je souhaiterais avoir un peu d'aide si possible,pour finir de réalisé un petit programme en c,Car j'ai rencontré des problè probleme de send en C avec socket [ par thorn74 ] bonjour je suis actuellement en IUT info et G un  projet a faire mais je bloque je doit fair eun petit programme ou lorsqu'un ordinateur se connecte a Connexion code C++ et Mysql [ par schadrac ] Bonjour je voudrais savoir comment connecter mon code C++ et une base de données Mysql qui fonctionne sous Wampserver et qui est disponible sur tout Probleme de conversion char int string... [ par pyr0123 ] Salut, Je code un échange de trames (t'chat) par port série entre 2 PC en C++ .net VStudio 2k5. J'envoie la chaine 'toto' du PC1 vers PC2, avec l'hyp connexion ftp c++ [ par Kyoshiro1501 ] Bonjour tout le monde,j'ai besoin d'uploader un fichier sur un ftp en c++ (avec des commande simples)j'ai trouver une aide a cette adresse http://www. Connexion serveur client réseau [ par matad0r ] Bonjour ! Ceci est mon premier post ! Voilà mon problème : j'ai créer deux applications, une cliente et une serveur. Mais le problème est que elle ne verification de code [ par dyroj ] salut a tous,je voudrai savoir si il y a des faute au niveu de la fonction select() et si je suis obliger de metre sock+1 au lieu de sock dans se peti


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

Photothèque

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,671 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales