cs_fredo2009
Messages postés17Date d'inscriptionlundi 20 novembre 2000StatutMembreDernière intervention 5 juillet 2006
-
1 juil. 2006 à 04:13
cs_fredo2009
Messages postés17Date d'inscriptionlundi 20 novembre 2000StatutMembreDernière intervention 5 juillet 2006
-
5 juil. 2006 à 09:49
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.
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);
}
excrt
Messages postés75Date d'inscriptionmercredi 5 avril 2006StatutMembreDernière intervention 3 juillet 2006 1 juil. 2006 à 21:00
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;
cs_fredo2009
Messages postés17Date d'inscriptionlundi 20 novembre 2000StatutMembreDernière intervention 5 juillet 2006 3 juil. 2006 à 03:03
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.
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 ^^
};
//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;
excrt
Messages postés75Date d'inscriptionmercredi 5 avril 2006StatutMembreDernière intervention 3 juillet 2006 3 juil. 2006 à 16:59
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);
#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:
cs_fredo2009
Messages postés17Date d'inscriptionlundi 20 novembre 2000StatutMembreDernière intervention 5 juillet 2006 5 juil. 2006 à 09:49
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.