同事需要一个 win 平台, 功能比较单一的端口扫描器, ip 地址从一个文件中导入, 每次运行指定一个端口.
以下是实现.
/*****************************************************************************
* Copyright : All Rights Reserved.
*
* Date : 2012-11-21 16:32:12
* Author/Corporation : Dengzhaoqun
* Email : dengzhaoqun@163.com
*****************************************************************************/
#include <afxmt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define IP_LEN 30
typedef struct IP_PORT
{
char *ip;
int port;
}IP_PORT_T;
int is_ip_port_open(const char *ip, const int port);
int scan_ips_port(const char *ip_file, const int port, int thread_num);
char *tr ( char *s );
UINT thread_connect_ip_port(LPVOID lpParam);
CSemaphore *p_semaphore;
int main(int argc, char *argv[])
{
if(argc < 4)
{
fprintf(stderr, "%s ip_file port thread_num\n", argv[0]);
return -1;
}
if(scan_ips_port(argv[1], atoi(argv[2]), atoi(argv[3]))!= 0)
{
fprintf(stderr, "scan_ips_port(%s, %s) failed\n", argv[1], argv[2]);
return -1;
}
printf("\n------- scan finished ---------\n");
return 0;
}
int scan_ips_port(const char *ip_file, const int port, int thread_num)
{
FILE *fp;
char ip[IP_LEN];
HANDLE handle;
DWORD ThreadID;
IP_PORT_T ip_port;
fp = fopen(ip_file, "r");
if(fp == NULL)
{
fprintf(stderr, "fopen %s failed: %s\n", ip_file, strerror(errno));
return -1;
}
CSemaphore semaphore(thread_num, thread_num);
p_semaphore = &semaphore;
while(fgets(ip, IP_LEN, fp) != NULL)
{
tr(ip);
ip_port.ip = ip;
ip_port.port = port;
WaitForSingleObject(semaphore.m_hObject,INFINITE);
if((handle = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)thread_connect_ip_port,
&ip_port,
0,
&ThreadID)) == NULL)
{
fprintf(stderr, "CreateThread failed\n");
ReleaseSemaphore(semaphore.m_hObject,1,NULL);
}
}
Sleep(10);
fclose(fp);
return 0;
}
char *tr ( char *s )
{
int i = 0;
int j = strlen ( s ) - 1;
int k = 0;
while ( isspace ( s[i] ) && s[i] != '\0' )
i++;
while ( isspace ( s[j] ) && j >= 0 )
j--;
while ( i <= j )
s[k++] = s[i++];
s[k] = '\0';
return s;
}
UINT thread_connect_ip_port(LPVOID lpParam)
{
IP_PORT_T *ip_port;
int result;
WORD wVersionRequested;
WSADATA wsaData;
int err;
SOCKET sockClient;
SOCKADDR_IN addrSrv;
ip_port = (IP_PORT_T *)lpParam;
wVersionRequested = MAKEWORD( 1, 1 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
perror("WSAStartup failed");
ReleaseSemaphore(p_semaphore->m_hObject,1,NULL);
return -1;
}
if (LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup( );
ReleaseSemaphore(p_semaphore->m_hObject,1,NULL);
return -1;
}
sockClient = socket(AF_INET, SOCK_STREAM, 0);
if(sockClient == INVALID_SOCKET)
{
perror("socket failed");
ReleaseSemaphore(p_semaphore->m_hObject,1,NULL);
return -1;
}
addrSrv.sin_addr.S_un.S_addr = inet_addr(ip_port->ip);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons((short)ip_port->port);
result = connect(sockClient, (SOCKADDR *)&addrSrv, sizeof(SOCKADDR));
if(result != 0)
{
fprintf(stdout, "%s %d closed\n", ip_port->ip, ip_port->port);
}
else
{
fprintf(stdout, "%s %d open\n", ip_port->ip, ip_port->port);
}
closesocket(sockClient);
WSACleanup();
ReleaseSemaphore(p_semaphore->m_hObject,1,NULL);
return 0;
}
执行 "scan_ips_port ips.txt 21 10" 即可, 10 为同时运行的最大线程数.