VC++多线程tcp connect扫描

本文介绍了一个基于Windows平台的端口扫描器程序的实现细节。该程序使用多线程技术来提高扫描效率,并通过设置超时时间来避免长时间阻塞。文章提供了完整的源代码,并解释了如何使用该程序进行端口范围的扫描。
#include "stdafx.h"

#include <stdlib.h>

#include <stdio.h>

#include <winsock2.h>

#include <time.h>

#pragma comment(lib,"ws2_32.lib")



char *host;

int threadnum,maxthread,totalport;

long nowport;



TIMEVAL timeout;

FD_SET    mask;

void usage(char *name)

{

printf("\t===================Portscaner======================\n");

printf("\t============gxisone@hotmail.com     2004/7/6=======\n");

printf("\tusage: %s IP StartPort-EndPort MaxThread(1000)\n",name);

printf("\tExample: %s 192.168.1.1 1-10000 500\n",name);

}



void display(void)  // 定义状态提示函数

{

static int play=0;

// 进度条

char *plays[12]=

{

" | ",

" / ",

" - ",

" \\ ",

" | ",

" / ",

" - ",

" // ",

" | ",

" / ",

" - ",

" // ",

};

printf("=%s=\t%d threads %d %s Completed. \r", plays[play],threadnum,nowport*100/(totalport+1),"%");

play=(play==11)?0:play+1;

Sleep(1);

}



void WaitThreadEnd(void)

{

Sleep(1000);

printf("\nThread ending....\n");

while(threadnum>0)

{

Sleep(1);

printf(" =|=\t%d threads \r",threadnum);



}

printf("\nThread ended!\n");

}

DWORD WINAPI ThreadFunc( LPVOID lp ) //线程函数,跟普通的函数没什么两样

{  

int port=*(DWORD*)lp;

    SOCKET sockfd;

    struct sockaddr_in addr;



    u_long value;

    addr.sin_family =AF_INET;

addr.sin_addr.s_addr =inet_addr(host);


value=1;



sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if(sockfd==INVALID_SOCKET)

    {  

printf("Socket error!\n");

InterlockedExchangeAdd((long *)&threadnum,-1);

        return 0;

    }

    ioctlsocket(sockfd,FIONBIO,&value);

addr.sin_port = htons(port);



    connect(sockfd,(struct sockaddr *) &addr, sizeof(addr));



    FD_ZERO(&mask);

    FD_SET(sockfd,&mask);

    value=select(0,NULL,&mask,NULL,&timeout);

    if(value==0 || value==-1)

    {   

closesocket(sockfd);

Sleep(50);

InterlockedExchangeAdd((long *)&threadnum,-1);

return 0;


    }

    else

{

shutdown(sockfd, 0);

printf("\t\tFound port %d open.\r\n",port);

closesocket(sockfd);

Sleep(50);

InterlockedExchangeAdd((long *)&threadnum,-1);

}




return 0;

}



VOID main( int argc,char **argv )

{


WSADATA ws;

char *p;

int startport,endport;

clock_t start,end;//程序运行的起始和结束时间

float costtime;//程序耗时

if(argc!=4)

{

usage(argv[0]);

return ;

}


long lresult;

lresult=WSAStartup(MAKEWORD(2,2), &ws);

p=argv[2];//处理端口参数

    if(strstr(argv[2],"-"))

    {    startport=atoi(argv[2]);

for(;*p;)

if(*(p++)=='-')break;

        endport=atoi(p);


        if(startport<1 || endport>65535)

        {   

printf("Port Error!\n");

            return;

        }

    }

host=argv[1];

maxthread=(atoi(argv[3])-1>999)?999:atoi(argv[3])-1;

    usage(argv[0]);

timeout.tv_usec=0;

if(maxthread>500)timeout.tv_sec=2;

else timeout.tv_sec=1;

start=clock();//开始计时

totalport=endport-startport;


for(int port=startport;port<endport;port++,nowport++,threadnum++)

{

display();

while(threadnum>maxthread)

{

Sleep(10);

}

CreateThread( NULL,0,ThreadFunc,&port, 0,NULL);

}

end=clock();//计时结束

costtime= (float)(end - start) / CLOCKS_PER_SEC;  //转换时间格式

printf("Cost time:%f Sec",costtime);//显示耗时

printf("\n\n");

WaitThreadEnd();


WSACleanup();

return ;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值