TA的每日心情 | 难过 2017-6-29 01:10 |
---|
签到天数: 376 天 [LV.9]以坛为家II
管理员
- 积分
- 13557
|
//首先 引入需要用到的库文件
#include <stdio.h>// 标准输入输出流
#include <winsock2.h>//socket套接字 网络发包性质的 网络通讯
#include <time.h>//时间的头文件
#pragma comment(lib,"ws2_32.lib")//编译链接用的库文件
//只有包含了这些头文件 才能引用里面的 函数方法
char *host;//定义字符型 变量 指针 保存主机IP
int threadnum,maxthread,totalport;//定义线程 端口
long nowport ;//当前端口
TIMEVAL timeout; //定义一个时间结构体的对象
FD_SET mask;
void display(void)
{
static int play=0;
char *plays[12]=
{
" | ",
" / ",
" - ",
" \\ ",
" | ",
" / ",
" - ",
" // ",
" | ",
" / ",
" - ",
" // ",
};
printf("=%s=\t%d 线程 %d %s 完成...\r",plays[play],threadnum,nowport*100/(totalport+1),"%");
play=(play==11)?0:play+1;
Sleep(1);
}
void WaitThreadEnd(void)
{
Sleep(1000);
printf("\n 线程结束中.....\n");
while (threadnum>0)
{
Sleep(1);
printf("=|=\t%d 线程数 \r",threadnum);
}
}
//最终的回调函数 线程
DWORD WINAPI ThreadFunc(LPVOID lp)
{
int port=*(DWORD*)lp;//得到端口
SOCKET sockfd;
struct sockaddr_in addr;// 套接字 地址的一个 结构体的 对象
u_long value;//定义一个 无符号的long;
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(host);
value=1;//非阻塞模式的参数
sockfd=socket(AF_INET,SOCK_STREAM,0);//初始化 流模式TCP
if (sockfd==INVALID_SOCKET)
{
printf("套接字错误\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\t 发现 %d 打开\r\n",port);
closesocket(sockfd);
Sleep(50);
InterlockedExchangeAdd((long *)&threadnum,-1);
}
return 0;
}
void usage(char *name)//传递一个参数进来 char类型
{
printf("\t========================猫猫专用扫描器=============================\n");
printf("\t========================QQ 图上有 2012.6.2========================\n\n");
printf("用法: 程序名 ip 开始端口-结束端口 线程\n\n",name);
printf("\t 程序名: 您的程序名%s\n",name);
printf("\t IP: 你想要扫描的IP地址\n");
printf("\t 端口: (1-65535之间的数)\n");
printf("\t 线程: 最大开到1000\n\n");
printf("使用例子: %s 192.168.1.1 1-65535 500 \n",name);
}
//定义main 主入口函数
void main(int argc,char **argv)
{
//初始化套接字
WSADATA ws;//初始化WSADATA
char *p;//一个指向端口的指针 就是我们传递的端口
int startport,endport;//定义两个整形变量 来保存开始 结束端口
clock_t start,end; // 检测程序扫描用了多少时间
float costtime;//花费的时间 float类型 浮点
if (argc!=4)//如果参数不等于4个
{
usage(argv[0]);//调用该函数 。。usage 传递 argv[0]
//第一个参数 默认指向的 是程序的名字
return;
}
long lresult; //定义长整型的变量
lresult=WSAStartup(MAKEWORD(2,2),&ws);// 进行开始wsadata
p=argv[2];//指针指向第三个参数 端口 第一个是程序名 第二个 IP 第三个才是端口
if (strstr(argv[2],"-")) //查找这个- 线 查找到之后 进入if体
{
startport=atoi(argv[2]);//比如: 222-333
for (;*p;)if(*(p++)=='-')break;
//得到的是p的值 其实就是无限循环 *p取出指针对应的值
endport=atoi(p);
if (startport<1 || endport>65535)
{
printf("端口你写错了吧 1-65535 之间的一个数\n");
return;
}
}
host=argv[1];//保存主机IP
maxthread=(atoi(argv[3]-1)>999)?999:atoi(argv[3])-1;
//三目运算 如果大于1000那么 等于999 否则 等于用户输入的
usage(argv[0]);//又输出了一次菜单
timeout.tv_usec=0;//初始化时间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("消耗时间: %f 秒",costtime);
printf("\n\n");
WaitThreadEnd();//等待线程结束
WSACleanup();//关闭套接字
return ;//返回
|
|