一个典型的TCP端口扫描器,通过用connect函数对服务器进行尝试连接来判断该服务器上的端口是否开放。这个扫描器是多线程的,现在的Winsock编程大多数采用多线程技术,这样可以充分利用带宽,如Netants的5个蚂蚁下载,一些FTP软件的多线程上传,等等!
//Source Code In C++Builder5
- #pragma hdrstop
- #include “Unit1.h”
- #define threadNum 10//线程数
- #define mutexName “Welcome to LoveBcb.yeah.net”
- #pragma package(smart_init)
- #pragma resource “*.dfm”
- typedef struct g_scan //这是一个自定义的结构
- {
- char szFile[40];//用于存放结果的文件名
- char szMutex[40];//用于存放互斥体的名字,这是多线程保证线程安全的一种方法
- unsigned short sPort;//扫描的起始端口,本机字节顺序
- unsigned short ePort;//扫描的终止端口,本机字节顺序
- unsigned long goalI;//目标主机IP,网络字节顺序
- int Result;//用于存放结果
- }*PG_SCAN;
- TForLover *ForLover;//这是窗体
- HANDLE hThread[threadNum];
- g_scan gscan[threadNum];
- DWORD dwThreadId,dwThreadCode;
- unsigned short usPart;//用于分割所要扫描的端口数,分配给各个线程
- unsigned long ulIp;
- int iLiveThread;//用于存放活动的线程数
- unsigned long ServerIp(char*serverip);
- DWORD WINAPI ScanPort(LPVOID lp)
- /*这是主线程函数ScanPort*/
- DWORD WINAPI ScanPort(LPVOID lp)
- {
- PG_SCAN pgscan=(PG_SCAN)lp;
- char szResult[40];
- sockaddr_in sock;
- unsigned short nowPort=pgscan→sPort-1;//用于存放当前扫描的端口号
- FILE*fp;//文件指针
- HANDLE hMutex=OpenMutex(MUTEX_ALL_ACCESS,false,pgscan→szMutex);
- SOCKET sk=socket(AF_INET,SOCK_STREAM,0);
- sock.sin_family=AF_INET;
- sock.sin_addr.s_addr=pgscan→goalIp;
- while(nowPort
- {
- sock.sin_port=htons(++nowPort)
- if(connect(sk,(sockaddr*)&sock,sizeof(sock))==SOCKET_ERROR)
- continue;
- /*由于这里用的是阻塞方式的套接字,所以返回SOCKET_ERROR一般意味着无法连接,于是用continue结束本次循环,即重新开始一次循环。如果返回值不是SOCKET_ERROR的话,表示连接成功,也就是说目标主机上开放了此端口*/
- wsprintf(szResult,“目标主机:%s端口:%d开放/r/n”,inet_ntoa(sock.sin_addr),nowPort); WaitForSingleObject(hMutex,INFINITE);
- /*用WaitForSinleObject保证线程安全INFINITE表示一直等待,直到互斥体有信号*/
- fp=fopen(pgscan→szFile,“a”);
- fwrite(szResult,sizeof(char),strlen(szResult),fp);
- fclose(fp);
- pgscan→Result++;
- ReleaseMutex(hMutex);//释放互斥体
- closesocket(sk);//由于已经建立了连接,所以这里要关闭连接
- sk=socket(AF_INET,SOCK_STREAM,0);//重新创建一个套接字
- }