C实现的非阻塞方式命令行端口扫描器源码

该实例是一个C实现的基于命令行模式端口扫描代码,并且是以非阻塞方式来实现对IP和端口的连接测试。为了大家使用和学习方便,已在代码中尽可能多的地方加入了注释,相信对于帮助大家理解C端口扫描有很大帮助。

具体功能代码如下:

#include 
#include 
// 编译时需使用的库
#pragma comment(lib,"wsock32.lib")
// select()成员定义
#define ZERO (fd_set *)0
// 变量定义
int maxth, scanok, scannum;
int portip, hoststart, hoststop, startport, endport; //定义了开始I和结束P地址,开始和结束端口
long searchnum, searched;
void usage(char *); // 定义显示使用方法函数
void playx(int); // 定义状态提示函数
void setip2(char *); // 定义设置IP函数
void customport(char *, char *, char *); // 定义自定义扫描端口函数
void portscannow(int); // 定义端口扫描扫描
int main(int argc, char *argv[])
{
WSADATA wsadata;
// 清屏
system("cls.exe");
// 显示版本信息
printf("\r\n============== 命令行端口扫描器 PortScanner V1.0 ==============");
// 检查输入
if ((argc < 3) || (argc > 4))
{
// 显示帮助提示
usage(argv[0]);
return -1;
}
// 检测是否为port扫描
if(!(stricmp(strlwr(argv[1]), "-p") == 0))
{
usage(argv[0]);
return -1;
}
// 程序初始化
if (WSAStartup(MAKEWORD(1,1), &wsadata) != 0) //如果初始化错误
{
printf("\r\nWsatartup error");      //出错信息
return -1;
}
// 端口扫描参数转换
// 如果参数为三个
if (argc == 3)
{
// 直接设置IP
setip2(argv[2]);
}
// 如果参数为四个
else
if (argc == 4)
{
// 进入定制端口扫描处理
customport(argv[0], argv[2], argv[3]);
}
// 参数过多显示帮助
else
{
usage(argv[0]);
return -1;
}
// 扫描端口开始
portscannow(argc);
WSACleanup();
return 0;
}
// 帮助提示函数
void usage(char * prog)
{
printf("Usage: %s 

为了测试该端口扫描器,可以使用如下连接测试代码进行测试,源码如下:

/*此函数实现判断m_server的m_port端口是否可以连上,超时限制为nTimeOut秒*/ 
BOOL ConnectTest(char * m_server,int m_port) 
{ 
    struct hostent* host = NULL; 
    struct sockaddr_in saddr; 
    unsigned int s = 0; 
    BOOL ret; 
    time_t start; 
    int error; 
    host = gethostbyname (m_server); 
    if (host==NULL)return FALSE; 

    saddr.sin_family = AF_INET; 
    saddr.sin_port = htons(m_port); 
    saddr.sin_addr = *((struct in_addr*)host->h_addr); 
    if( (s=socket(AF_INET, SOCK_STREAM, 0))<0){ 
        return FALSE; 
    } 
    fcntl(s,F_SETFL, O_NONBLOCK); 

    if(connect(s,(struct sockaddr*)&saddr, sizeof(saddr)) == -1) { 
        if (errno == EINPROGRESS){// it is in the connect process 
            struct timeval tv; 
            fd_set writefds; 
            tv.tv_sec = m_nTimeOut; 
            tv.tv_usec = 0; 
            FD_ZERO(&writefds); 
            FD_SET(s, &writefds); 
            if(select(s+1,NULL,&writefds,NULL,&tv)>0){ 
                int len=sizeof(int); 
                //下面的一句一定要,主要针对防火墙 
                getsockopt(s, SOL_SOCKET, SO_ERROR, &error, &len); 
                if(error==0) ret=TRUE; 
                else ret=FALSE; 
            }else  ret=FALSE;//timeout or error happen 
        }else ret=FALSE; 
    } 
    else  ret=TRUE; 
    close(s); 
    return ret; 
}

你可能感兴趣的:(C实现的非阻塞方式命令行端口扫描器源码)