muskad202
asked on
portscanner, works slow in windows
hi !!
i had made a small utility sometime back that did a portscan on a given ip. i was using it in linux, and it worked fine .. i.e, it was fast enough. the basic thing that i was doing was a connect, and then checking the return code to determine whether the port was open or not. scanning all ports from 1 to 65536 took abt 10 seconds
i then tried using the same code, with minor changes, e.g, had to add WSAStartup(), .. etc, to make it work on windows so that i could integrate it into another program. the problem is, it works really slow on windows ... scanning ports 22 to 30 (i.e, only 9 ports) takes over 5 seconds ..
anyone know what culd be the problem ??
////////////////////////// ////////// ////////// ////////// ////////
//Code
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),& wsad);
struct sockaddr_in thePC;
memset(&thePC,0,sizeof(the PC));
thePC.sin_family=AF_INET;
///Getting the IPAddress from the IPAddress control
DWORD IPAddress;
SendMessage(IPToPortScan,I PM_GETADDR ESS,0,(LPA RAM)(LPDWO RD)&IPAddr ess);
IPAddress = ntohl(IPAddress);
memcpy((void*)&thePC.sin_a ddr.S_un,& IPAddress, sizeof(IPA ddress));
unsigned int theP;
char thePort[8];
for (theP=22;theP<=30;theP++)
{
SOCKET SockFDS = socket(AF_INET,SOCK_STREAM ,0);
thePC.sin_port=htons(theP) ;
int n = connect(SockFDS,(sockaddr* )&thePC,si zeof(thePC ));
if (n>=0)
{
itoa(theP,thePort,10);
SendMessage(ListOfOpenPort s,LB_ADDST RING,0,(LP ARAM)thePo rt);
UpdateWindow(ListOfOpenPor ts);
}
closesocket(SockFDS);
}
WSACleanup();
////////////////////////// /////////
Thanks :-)
muskad202
i had made a small utility sometime back that did a portscan on a given ip. i was using it in linux, and it worked fine .. i.e, it was fast enough. the basic thing that i was doing was a connect, and then checking the return code to determine whether the port was open or not. scanning all ports from 1 to 65536 took abt 10 seconds
i then tried using the same code, with minor changes, e.g, had to add WSAStartup(), .. etc, to make it work on windows so that i could integrate it into another program. the problem is, it works really slow on windows ... scanning ports 22 to 30 (i.e, only 9 ports) takes over 5 seconds ..
anyone know what culd be the problem ??
//////////////////////////
//Code
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),&
struct sockaddr_in thePC;
memset(&thePC,0,sizeof(the
thePC.sin_family=AF_INET;
///Getting the IPAddress from the IPAddress control
DWORD IPAddress;
SendMessage(IPToPortScan,I
IPAddress = ntohl(IPAddress);
memcpy((void*)&thePC.sin_a
unsigned int theP;
char thePort[8];
for (theP=22;theP<=30;theP++)
{
SOCKET SockFDS = socket(AF_INET,SOCK_STREAM
thePC.sin_port=htons(theP)
int n = connect(SockFDS,(sockaddr*
if (n>=0)
{
itoa(theP,thePort,10);
SendMessage(ListOfOpenPort
UpdateWindow(ListOfOpenPor
}
closesocket(SockFDS);
}
WSACleanup();
//////////////////////////
Thanks :-)
muskad202
I suspect that it is related to SendMessage/UpdateWindow and the fact that your message pump isn't pumped. Is it faster if you use PostMessage instead of SendMessage and finish up with a PostMessage to update the window? Sorry, I'm not much of a Windows programmer... this is pure guess-work!
> finish up with a PostMessage to update the window
i.e. don't call UpdateWindow(ListOfOpenPor ts) locally, but do that in a message handler
i.e. don't call UpdateWindow(ListOfOpenPor
ASKER
its nothing to do with UpdateWindow/SendMessage ... etc.. its a problem in winsock. Even if i rewrite the code as below..its equally slow
-------------------------- ---------- ---------- ---------- ---------- ---------
#include <stdio.h>
#include <winsock2.h>
void main()
{
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),& wsad);
struct sockaddr_in thePC;
memset(&thePC,0,sizeof(the PC));
thePC.sin_family=AF_INET;
thePC.sin_addr.S_un.S_addr =inet_addr ("10.108.7 .52");
unsigned int theP;
char thePort[8];
for (theP=20;theP<=30;theP++)
{
SOCKET SockFDS = socket(AF_INET,SOCK_STREAM ,0);
thePC.sin_port=htons(theP) ;
int n = connect(SockFDS,(sockaddr* )&thePC,si zeof(thePC ));
if (n>=0)
{
itoa(theP,thePort,10);
printf("%s\n",thePort);
}
closesocket(SockFDS);
}
WSACleanup();
}
-------------------------- ---------- ---------- --------
--------------------------
#include <stdio.h>
#include <winsock2.h>
void main()
{
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),&
struct sockaddr_in thePC;
memset(&thePC,0,sizeof(the
thePC.sin_family=AF_INET;
thePC.sin_addr.S_un.S_addr
unsigned int theP;
char thePort[8];
for (theP=20;theP<=30;theP++)
{
SOCKET SockFDS = socket(AF_INET,SOCK_STREAM
thePC.sin_port=htons(theP)
int n = connect(SockFDS,(sockaddr*
if (n>=0)
{
itoa(theP,thePort,10);
printf("%s\n",thePort);
}
closesocket(SockFDS);
}
WSACleanup();
}
--------------------------
I've just tried this myself, and it looks like the Berkley sockets implementation in Winsock doesn't detect connect failure quickly as you surmised. Sorry for the bum steer.
You get good results, if you make sockets non-blocking for the connect and select looking for exceptions or writable descriptors:
--------8<--------
#include <iostream>
#include <winsock2.h>
bool missing_result(bool [],int);
int main()
{
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),& wsad);
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr ));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("10.108.7.52");
const unsigned short first_port = 20;
const int ports = 10;
SOCKET sock[ports];
bool result[ports];
bool listening[ports];
unsigned long now_nonblocking = 1;
for (int i = 0;i < ports;i++) {
sock[i] = socket(AF_INET,SOCK_STREAM ,0);
ioctlsocket(sock[i],FIONBI O,&now_non blocking); // Make it a non-blocking
addr.sin_port=htons(first_ port+i);
if (connect(sock[i],(sockaddr *)&addr,si zeof(addr) ) != -1) // Non-blocking connect attempt
listening[i] = result[i] = true; // Immediate success is unlikely, but possible
else
result[i] = false; // More likely to have to wait for a result
}
while (missing_result(result,por ts)) { // While we are waiting for results
fd_set wdesc,edesc;
FD_ZERO(&wdesc); // This picks up on connection successes
FD_ZERO(&edesc); // This picks up on connection failures
for (int i = 0;i < ports;i++)
if (!result[i]) {
FD_SET(sock[i],&wdesc);
FD_SET(sock[i],&edesc);
}
select(sock[ports-1]+1,(fd _set*)0,&w desc,&edes c,0);
for (int i = 0;i < ports;i++)
if (FD_ISSET(sock[i],&wdesc)) {
listening[i] = result[i] = true;
//std::cout << "Listening on port " << first_port+i << '\n';
}
else if (FD_ISSET(sock[i],&edesc)) {
listening[i] = false;
result[i] = true;
//std::cout << "Not listening on port " << first_port+i << '\n';
}
}
WSACleanup();
for (int i = 0;i < ports;i++)
if (listening[i])
std::cout << "Listening on port " << first_port+i << '\n';
}
bool missing_result(bool result[],int ports)
{
for (int i = 0;i < ports;i++)
if (result[i] == false)
return true;
return false;
}
--------8<--------
You get good results, if you make sockets non-blocking for the connect and select looking for exceptions or writable descriptors:
--------8<--------
#include <iostream>
#include <winsock2.h>
bool missing_result(bool [],int);
int main()
{
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),&
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("10.108.7.52");
const unsigned short first_port = 20;
const int ports = 10;
SOCKET sock[ports];
bool result[ports];
bool listening[ports];
unsigned long now_nonblocking = 1;
for (int i = 0;i < ports;i++) {
sock[i] = socket(AF_INET,SOCK_STREAM
ioctlsocket(sock[i],FIONBI
addr.sin_port=htons(first_
if (connect(sock[i],(sockaddr
listening[i] = result[i] = true; // Immediate success is unlikely, but possible
else
result[i] = false; // More likely to have to wait for a result
}
while (missing_result(result,por
fd_set wdesc,edesc;
FD_ZERO(&wdesc); // This picks up on connection successes
FD_ZERO(&edesc); // This picks up on connection failures
for (int i = 0;i < ports;i++)
if (!result[i]) {
FD_SET(sock[i],&wdesc);
FD_SET(sock[i],&edesc);
}
select(sock[ports-1]+1,(fd
for (int i = 0;i < ports;i++)
if (FD_ISSET(sock[i],&wdesc))
listening[i] = result[i] = true;
//std::cout << "Listening on port " << first_port+i << '\n';
}
else if (FD_ISSET(sock[i],&edesc))
listening[i] = false;
result[i] = true;
//std::cout << "Not listening on port " << first_port+i << '\n';
}
}
WSACleanup();
for (int i = 0;i < ports;i++)
if (listening[i])
std::cout << "Listening on port " << first_port+i << '\n';
}
bool missing_result(bool result[],int ports)
{
for (int i = 0;i < ports;i++)
if (result[i] == false)
return true;
return false;
}
--------8<--------
Tabulation was horrible then, I'll post that code again:
--------8<--------
#include <iostream>
#include <winsock2.h>
bool missing_result(bool [],int);
int main()
{
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),& wsad);
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr ));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.51.87") ;
const unsigned short first_port = 20;
const int ports = 10;
SOCKET sock[ports];
bool result[ports];
bool listening[ports];
unsigned long now_nonblocking = 1;
for (int i = 0;i < ports;i++) {
sock[i] = socket(AF_INET,SOCK_STREAM ,0);
ioctlsocket(sock[i],FIONBI O,&now_non blocking);
addr.sin_port=htons(first_ port+i);
if (connect(sock[i],(sockaddr *)&addr,si zeof(addr) ) != -1)
listening[i] = result[i] = true;
else
result[i] = false;
}
while (missing_result(result,por ts)) {
fd_set wdesc,edesc;
FD_ZERO(&wdesc);
FD_ZERO(&edesc);
for (int i = 0;i < ports;i++)
if (!result[i]) {
FD_SET(sock[i],&wdesc);
FD_SET(sock[i],&edesc);
}
select(sock[ports-1]+1,(fd _set*)0,&w desc,&edes c,0);
for (int i = 0;i < ports;i++)
if (FD_ISSET(sock[i],&wdesc)) {
listening[i] = result[i] = true;
//std::cout << "Listening on port " << first_port+i << '\n';
}
else if (FD_ISSET(sock[i],&edesc)) {
listening[i] = false;
result[i] = true;
//std::cout << "Not listening on port " << first_port+i << '\n';
}
}
WSACleanup();
for (int i = 0;i < ports;i++)
if (listening[i])
std::cout << "Listening on port " << first_port+i << '\n';
}
bool missing_result(bool result[],int ports)
{
for (int i = 0;i < ports;i++)
if (result[i] == false)
return true;
return false;
}
--------8<--------
--------8<--------
#include <iostream>
#include <winsock2.h>
bool missing_result(bool [],int);
int main()
{
WSADATA wsad;
WSAStartup(MAKEWORD(2,0),&
struct sockaddr_in addr;
memset(&addr,0,sizeof(addr
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.51.87")
const unsigned short first_port = 20;
const int ports = 10;
SOCKET sock[ports];
bool result[ports];
bool listening[ports];
unsigned long now_nonblocking = 1;
for (int i = 0;i < ports;i++) {
sock[i] = socket(AF_INET,SOCK_STREAM
ioctlsocket(sock[i],FIONBI
addr.sin_port=htons(first_
if (connect(sock[i],(sockaddr
listening[i] = result[i] = true;
else
result[i] = false;
}
while (missing_result(result,por
fd_set wdesc,edesc;
FD_ZERO(&wdesc);
FD_ZERO(&edesc);
for (int i = 0;i < ports;i++)
if (!result[i]) {
FD_SET(sock[i],&wdesc);
FD_SET(sock[i],&edesc);
}
select(sock[ports-1]+1,(fd
for (int i = 0;i < ports;i++)
if (FD_ISSET(sock[i],&wdesc))
listening[i] = result[i] = true;
//std::cout << "Listening on port " << first_port+i << '\n';
}
else if (FD_ISSET(sock[i],&edesc))
listening[i] = false;
result[i] = true;
//std::cout << "Not listening on port " << first_port+i << '\n';
}
}
WSACleanup();
for (int i = 0;i < ports;i++)
if (listening[i])
std::cout << "Listening on port " << first_port+i << '\n';
}
bool missing_result(bool result[],int ports)
{
for (int i = 0;i < ports;i++)
if (result[i] == false)
return true;
return false;
}
--------8<--------
Sorry I just realised that was C++... do you want a C version or is that OK?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
works like a charm !!! :)
one thing .. i thought linux and windows both used berkley sockets .. then how come it works different on both ??
thanks :)
muskad202
one thing .. i thought linux and windows both used berkley sockets .. then how come it works different on both ??
thanks :)
muskad202
ASKER
also .. is there any way to set a timeout for a connect ??
The Berkley sockets API was evolved for UNIX. I think Microsoft implemented the Berkley API for Windows on top of its own Winsock API, which is more tightly bound to the Winsock TCP/IP protocol stack. If you want to write relatively portable code, it is best to go with the Berkley API, but if you want to specialise for Windows, you'll probably get better performace if you get into the intestines of Winsock API programming.
If you look at the ConnectEx spiel at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connectex_2.asp?frame=true you'll see that you can use getsockopt with SO_CONNECT_TIME to see if a connection is established and you could abort the connection by doing DisconnectEx. I've not played around with this stuff, but I'm sure you'll find experts on EE who have.
If you look at the ConnectEx spiel at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winsock/winsock/connectex_2.asp?frame=true you'll see that you can use getsockopt with SO_CONNECT_TIME to see if a connection is established and you could abort the connection by doing DisconnectEx. I've not played around with this stuff, but I'm sure you'll find experts on EE who have.