Speedup Windows C Port Scanner -
so developed port scanner c on windows have noticed on ip's runs slowly. here's code it:
dword winapi connectportw(lpvoid lpparam) { handle hstdout; pmydata pdataarray; wsadata firstsock; socket s; struct sockaddr_in sa; int err; char * openports = (char *)malloc(sizeof(char)*256); memset(&openports[0], 0, strlen(openports)); hstdout = getstdhandle(std_output_handle); if(hstdout == invalid_handle_value ) { return 1; } pdataarray = (pmydata)lpparam; strncpy((char *)&sa,"",sizeof sa); sa.sin_family = af_inet; if (wsastartup(makeword(2,0),&firstsock) != 0) { fprintf(stderr,"wsastartup() failed"); exit(1); } sa.sin_addr.s_addr = inet_addr(pdataarray->ip); s = socket(af_inet, sock_stream, 0); //make net valid socket handle if(s < 0) { perror("\nsocket creation failed"); // perror function prints error message stderr exit(1); } sa.sin_port = htons(pdataarray->port); err = connect(s, (struct sockaddr *)&sa, sizeof sa); //connection not accepted if(err == socket_error) { printf("%s %-5d winsock error code : %d\n", pdataarray->ip, pdataarray->port, wsagetlasterror()); strcpy("null", openports); fflush(stdout); } //connection accepted else { printf("%s %-5d accepted \n", pdataarray->ip, pdataarray->port); sprintf(openports, "%i,", pdataarray->port); if(shutdown(s, sd_both ) == socket_error ) { perror("\nshutdown"); exit(1); } } closesocket(s); fflush(stdout); strcpy(pdataarray->openports, openports); free(openports); return 0; } keep in mind use threads , each thread calls function different port (0 - 1024) on same ip.
so how can speed up? keep seeing people talking non-blocking, speed , if how can implement that. thanks!
edit: taking 614 seconds (10 minutes) scan 0 - 1024 on 1 of aforementioned 'slow' ip's
edit 2: started trying use non-blocking... doing right?
ioctlsocket(s, fionbio, &on); connect(s, (struct sockaddr *)&sa, sizeof sa); fd_zero(&fds); fd_set(s, &fds); err = select(s, &fds, &fds, &fds, &tv); if (err != socket_error && err != 0) { sprintf(openports + strlen(openports),"%i,", pdataarray->port); } closesocket(s); edit 3: seems new method giving me inaccurate results much faster. seem getting more open ports compared results of running nmap on same ip.
i see lot of problems thread code:
it leaking memory if failure happens.
you misusing
strlen()when callingmemset()onopenportsvariable. removememset()altogether , usecalloc()orlocalalloc(lmem_zeroinit)instead when allocatingopenports. or, use call stack instead, since variable small:char openports[256] = {0};or better, don't use localopenportsvariable @ all, writepdataarray->openportsdirectly when have result available.you should not using
exit()@ all. usereturninstead.it not technically illegal call
wsastartup()/wsacleanup()multiple times, since winsock reference counted, best call them once @ program startup/exit, not per thread. but, since callingwsastartup(), must callwsacleanup()keep winsock reference count balanced.what trying
strcpy("null", openports);? writing read-only memory. think meanstrcpy(openports, "null");instead.writing
pdataarray->openportsnot thread-safe if multiple threads sharing single buffer (your use of,insprintf()string implies may case). need synchronize access buffer when writing across multiple threads. can use critical section or mutex purpose.
that being said, using blocking socket, connect() block thread until winsock times out internally, may take awhile on slow networks. speed up, switch socket non-blocking mode using ioctrlsocket(fionbio), , use select() implement own timeout connect(), eg:
dword winapi connectportw(lpvoid lpparam) { pmydata pdataarray = (pmydata) lpparam; handle hstdout = getstdhandle(std_output_handle); if (hstdout == invalid_handle_value) return 1; wsadata wsa; int err = wsastartup(makeword(2,0), &wsa); if (err != 0) { fprintf(stderr, "%s %d wsastartup() failed, error code : %d\n", pdataarray->ip, pdataarray->port, err); return 1; } socket s = socket(af_inet, sock_stream, 0); //make net valid socket handle if (s == invalid_socket) { fprintf(stderr, "%s %d socket creation failed, error code : %d\n", pdataarray->ip, pdataarray->port, wsagetlasterror()); wsacleanup(); return 1; } u_long enabled = 1; if (ioctlsocket(s, fionbio, &enabled) == socket_error) { fprintf(stderr, "%s %d socket non-blocking mode failed, error code : %d\n", pdataarray->ip, pdataarray->port, wsagetlasterror()); closesocket(s); wsacleanup(); return 1; } struct sockaddr_in sa = {0}; sa.sin_family = af_inet; sa.sin_addr.s_addr = inet_addr(pdataarray->ip); sa.sin_port = htons(pdataarray->port); if (connect(s, (struct sockaddr *)&sa, sizeof sa) == socket_error) { err = wsagetlasterror(); if (err != wsaewouldblock) { fprintf(stderr, "%s %d socket connect failed, error code : %d\n", pdataarray->ip, pdataarray->port, err); closesocket(s); wsacleanup(); return 1; } fd_set wfd, efd; fd_zero(s, &wfd); fd_set(s, &wfd); fd_zero(s, &efd); fd_set(s, &efd)' timeval timeout; timeout.tv_sec = 5; timeout.tv_usec = 0; err = select(0, null, &wfd, &efd, &timeout); if (err == socket_error) { fprintf(stderr, "%s %d socket select failed, error code : %d\n", pdataarray->ip, pdataarray->port, wsagetlasterror()); closesocket(s); wsacleanup(); return 1; } if (err == 0) { // connect timeout closesocket(s); wsacleanup(); return 0; } if (fd_isset(s, &efd)) { err = 0; getsockopt(s, sol_socket, so_error, (char*)&err, sizeof err); closesocket(s); wsacleanup(); switch (err) { case wsaetimedout: // connect timeout case wsaeconnrefused: // port closed return 0; } fprintf(stderr, "%s %d socket connect failed, error code : %d\n", pdataarray->ip, pdataarray->port, err); return 1; } } // connected! printf("%s %d accepted\n", pdataarray->ip, pdataarray->port); // note, not thread-safe! need sync access openports... sprintf(pdataarray->openports + strlen(pdataarray->openports), "%d,", pdataarray->port); closesocket(s); wsacleanup(); return 0; }
Comments
Post a Comment