Accueil > Forum > > > > problème avec WSAGetLastError()
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
Livres en rapport
|
Derniers Blogs
TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Vincent Bellet et Baptiste Giraudier La BI dans SharePoint 2010, Les nouveaux services d'application dans SP2010 et SQL Server Reporting services 2008 R2. La BI dans SharePoint est généralisée pour tous afin de permettre à tous les coll...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2010 : PLAN DE MIGRATION VERS SHAREPOINT 2010TECHDAYS PARIS 2010 : PLAN DE MIGRATION VERS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Arnault Nouvel et Antoine Dongois Le processus à prendre : Apprendre (découvrir la plateforme) Préparer (documenter l'historique et choisir la méthode de MAJ) Test (Test de MAJ) Implémenter (Effectuer la MAJ) Valid...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice TECHDAYS PARIS 2010 : LA PLEINIèRE DU SECOND JOURTECHDAYS PARIS 2010 : LA PLEINIèRE DU SECOND JOUR par ROMELARD Fabrice
Après un retour sur l'histoire des TechDays de Paris et le fait que ce soit le plus gros event MS au monde (du fait de sa gratuité), le président de MS France (Eric Boustoullier) a fait une présentation de la vision Microsoft pour les années à venir...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
DB-MAIN (9.1.0)DB-MAIN (9.1.0)DB-MAIN is a data-modeling and data-architecture tool. It is designed to help developers and anal... Cliquez pour télécharger DB-MAIN Xilisoft DPG Convertisseur (5.1.37.0120)XILISOFT DPG CONVERTISSEUR (5.1.37.0120)Xilisoft DPG Convertisseur offre aux fans de Nintendo DS une bonne solution leur permettant de dé... Cliquez pour télécharger Xilisoft DPG Convertisseur GraphicsGale (2.01.01)GRAPHICSGALE (2.01.01)GraphicsGale est un logiciel de PixelArt avec de nombreuse fonctionnalités permettant de réalisé ... Cliquez pour télécharger GraphicsGale Architecte 3D (Platinum 2010)ARCHITECTE 3D (PLATINUM 2010)Architecte 3D Platinium vous permet de concevoir facilement les plans votre future maison, de l'é... Cliquez pour télécharger Architecte 3D TeamViewer 5 (TeamViewer 5)TEAMVIEWER 5 (TEAMVIEWER 5)Dépanner un ami,expliquer une manipulation devient un jeu d'enfant.
Prise en main d'un autre ord... Cliquez pour télécharger TeamViewer 5
|