Chinaunix首页 | 论坛 | 博客
  • 博客访问: 417287
  • 博文数量: 54
  • 博客积分: 1186
  • 博客等级: 少尉
  • 技术积分: 668
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-11 04:57
文章分类

全部博文(54)

文章存档

2013年(1)

2012年(6)

2011年(47)

我的朋友

分类: C/C++

2011-05-12 11:16:17

以非阻塞方式来实现对IP和端口的连接测试,非阻塞的socket我一直不会用,这段代码有空可以拿来学习学习。

  1. #include <afxext.h>
  2. #include <winsock.h>
  3. // 编译时需使用的库
  4. #pragma comment(lib,"wsock32.lib")
  5. // select()成员定义
  6. #define ZERO (fd_set *)0
  7. // 变量定义
  8. int maxth, scanok, scannum;
  9. int portip, hoststart, hoststop, startport, endport; //定义了开始I和结束P地址,开始和结束端口
  10. long searchnum, searched;
  11. void usage(char *); // 定义显示使用方法函数
  12. void playx(int); // 定义状态提示函数
  13. void setip2(char *); // 定义设置IP函数
  14. void customport(char *, char *, char *); // 定义自定义扫描端口函数
  15. void portscannow(int); // 定义端口扫描扫描

  16. // 主程序
  17. int main(int argc, char *argv[])
  18. {
  19. WSADATA wsadata;
  20. // 清屏
  21. system("cls.exe");
  22. // 显示版本信息
  23. printf("\r\n==================== HUC Command Line PortScanner V0.2 ====================");
  24. printf("\r\n=============== By Lion, Welcome to ===============\r\n\n");

  25. // 检查输入
  26. if ((argc < 3) || (argc > 4))
  27. {
  28. // 显示帮助提示
  29. usage(argv[0]);
  30. return -1;
  31. }

  32. // 检测是否为port扫描
  33. if(!(stricmp(strlwr(argv[1]), "-p") == 0))
  34. {
  35. usage(argv[0]);
  36. return -1;
  37. }

  38. // 程序初始化
  39. if (WSAStartup(MAKEWORD(1,1), &wsadata) != 0) //如果初始化错误
  40. {
  41. printf("\r\nWsatartup error"); //出错信息
  42. return -1;
  43. }

  44. // 端口扫描参数转换
  45. // 如果参数为三个
  46. if (argc == 3)
  47. {
  48. // 直接设置IP
  49. setip2(argv[2]);
  50. }
  51. // 如果参数为四个
  52. else
  53. if (argc == 4)
  54. {
  55. // 进入定制端口扫描处理
  56. customport(argv[0], argv[2], argv[3]);
  57. }
  58. // 参数过多显示帮助
  59. else
  60. {
  61. usage(argv[0]);
  62. return -1;
  63. }

  64. // 扫描端口开始
  65. portscannow(argc);
  66.   
  67. WSACleanup();
  68. return 0;
  69. }

  70. // 帮助提示函数
  71. void usage(char * prog)
  72. {
  73. printf("Usage: %s , prog);
  74. printf("\r\n\n );
  75. printf("\r\n -p [ Port|StartPort-EndPort ] < HostName|IP|StartIP-EndIP >");
  76. printf("\r\n\n Example: ");
  77. printf("\r\n %s -p 192.168.0.1", prog);
  78. printf("\r\n %s -p 192.168.0.1-192.168.0.254", prog);
  79. printf("\r\n %s -p 21-80 192.168.0.1", prog);
  80. printf("\r\n %s -p 21-80 192.168.0.1-192.168.0.254\r\n", prog);
  81. return;
  82. }

  83. // 进度提示
  84. void playx(int play = 0)
  85. {
  86. // 进度条
  87. char *plays[12]=
  88. {
  89. " | ",
  90. " / ",
  91. " - ",
  92. " \\ ",
  93. " | ",
  94. " / ",
  95. " - ",
  96. " \\ ",
  97. " | ",
  98. " / ",
  99. " - ",
  100. " \\ ",
  101. };

  102. if (searchnum != 0)
  103. {
  104. for (int i = 0 ; i <= 3; i ++)
  105. {
  106.   printf(" =%s= %d%s Completed. \r", plays , searched * 100 / (searchnum + 1), "%");
  107.   Sleep(5);
  108. }
  109. }
  110. else
  111. {
  112.   printf(" =%s=\r", plays[play]); //显示进度
  113.   Sleep(10);
  114. }
  115. }

  116. // 设置IP
  117. void setip2(char *cp)
  118. {
  119. int host;
  120. struct hostent *testhost;
  121. char *startip = "", *endip = "";

  122. // 判断是否为 192.168.0.1-192.168.0.254 形式的输入
  123. if (strstr(cp, "-") && strlen(cp) > 15 && strlen(cp) < 32)
  124. {
  125. // 提取出结束IP
  126. endip = strchr(cp, '-') + 1;
  127. // 提取出开始IP
  128. strncpy(startip, cp, strlen(cp) - strlen(strchr(cp, '-')));

  129. // 给控制要扫描IP段的变量赋值
  130. hoststart = ntohl(inet_addr(startip));
  131. hoststop = ntohl(inet_addr(endip));
  132. }
  133. else
  134. {
  135. // 取得输入的主机地址
  136. testhost = gethostbyname(startip);
  137.   
  138. // 如果地址不存在
  139. if(!testhost)
  140. {
  141.   WSACleanup( );
  142.   printf("\r\nCan't get ip of: %s", cp);
  143.   exit(-1);
  144. }
  145. // 给控制要扫描IP段的变量赋值
  146. memcpy(&host, testhost->h_addr, 4);
  147. hoststop = hoststart = ntohl(host);
  148. }
  149. }

  150. // 测试线程是否已满
  151. void TestThread(int thread = 200)
  152. {
  153. for (;;)
  154. {
  155. playx();

  156. // 测试线程是否已满
  157. if (maxth > thread)
  158.   Sleep(100);
  159. else break;
  160. }
  161. return;
  162. }

  163. // 等待线程结束函数
  164. void WaitThreadEnd()
  165. {
  166. // 延时
  167. Sleep(6000);
  168.   
  169. // 显示等待提示
  170. printf("\r \r\n");
  171. printf(" Wait ( %d )Thread end...\r\n", maxth);
  172.   
  173. for(;;)
  174. {
  175. // 判断所有线程是否已经结束
  176. if (maxth > 0)
  177. {
  178.   // 延时等待线程序结束
  179.   Sleep(100);
  180.   playx();
  181.   continue;
  182. }
  183. else break;
  184. }
  185. printf("\r\n");
  186. return;
  187. }

  188. // 定制端口扫描参数定义
  189. void customport(char *cp, char *cp2, char *cp3)
  190. {
  191. int intport;
  192. char *checker;

  193. // 处理要扫描的端口
  194. // 扫描开始端口变量赋值
  195. startport = atoi(cp2);
  196. // 扫描结束端口变量赋值
  197. endport = atoi(cp2);
  198.   
  199. // 判断是否 21-80 形式
  200. if (strstr(cp2,"-"))
  201. {
  202. intport = atoi(checker = strchr(cp2, '-') + 1);
  203. if (intport > 0 && intport < 65536)
  204.   // 扫描结束端口变量赋值
  205.   endport = intport;
  206. }

  207. // 端口大小判断
  208. if (startport < 0 || startport > 65536 || endport < 0 || endport > 65535)
  209. {
  210. usage(cp);
  211. exit(-1);
  212. }
  213. // 处理ip地址
  214. setip2(cp3);
  215. }

  216. // 端口扫描函数
  217. UINT portscan(LPVOID port)
  218. {
  219. int addr = portip; // 取得要扫描的地址
  220. int sock;
  221. struct fd_set mask;
  222. struct timeval timeout;
  223. struct sockaddr_in server;
  224. unsigned long flag = 1;

  225. // 创建一个sock
  226. sock = socket(AF_INET, SOCK_STREAM, 0);

  227. // 创建sock失败处理
  228. if (sock == INVALID_SOCKET)
  229. {
  230. printf("\r\nSock Error:%s", WSAGetLastError());
  231. maxth --;
  232. return -1;
  233. }
  234.   
  235. // 给sock成员赋值
  236. server.sin_family=AF_INET;
  237. server.sin_addr.s_addr = htonl(addr); // 要扫描的地址
  238. server.sin_port = htons(port); // 要扫描的端口

  239. // 显示进度
  240. playx();

  241. // 调用ioctlsocket()设置套接字为非阻塞模式
  242. if (ioctlsocket(sock, FIONBIO, &flag) != 0)
  243. {
  244. // 设置失败处理
  245. printf("\r\nSock Error:%s", WSAGetLastError());
  246. closesocket(sock);
  247. maxth --;
  248. return -1;
  249. }
  250.   
  251. // 调用connect()连接远程主机端口
  252. connect(sock, (struct sockaddr*)&server, sizeof(server));

  253. timeout.tv_sec = 18; // 超时限制为18秒
  254. timeout.tv_usec = 0;
  255. FD_ZERO(&mask); // 清空集合mask
  256. FD_SET(sock, &mask); // 将sock放入集合mask中
  257.   
  258. // 用select() 处理扫描结果
  259. switch(select(sock + 1, ZERO, &mask, ZERO, &timeout))
  260. {
  261. case -1:
  262. {
  263.   printf("\r\nSelect() error");
  264.   maxth --;
  265.   return -1;
  266. }

  267. // sock超时处理
  268. case 0:
  269. {
  270.   maxth --;
  271.   closesocket(sock);
  272.   return -1;
  273. }

  274. default:
  275. if(FD_ISSET(sock, &mask))
  276. {
  277.   // 禁止sock发送和接受数据
  278.   shutdown(sock, 0);
  279.   
  280.   // 设置输出结果格式
  281.   printf(" [Found:] %s Port: %d open.\r\n", inet_ntoa(server.sin_addr), ntohs(server.sin_port));
  282.   
  283.   // 关闭sock
  284.   closesocket(sock);
  285.   scanok ++;
  286.   maxth --;
  287.   return 1;
  288. }
  289. }
  290. return 0;
  291. }

  292. // 扫描开始主函数
  293. void portscannow(int xp)
  294. {
  295. int sport;
  296. char *timenow, timebuf[32];

  297. // 定义默认扫描的端口
  298. char *ports[32]={
  299. "21",
  300. "22",
  301. "23",
  302. "25",
  303. "53",
  304. "79",
  305. "80",
  306. "110",
  307. "111",
  308. "113",
  309. "123",
  310. "135",
  311. "139",
  312. "143",
  313. "443",
  314. "512",
  315. "513",
  316. "514",
  317. "515",
  318. "540",
  319. "1080",
  320. "1433",
  321. "1521",
  322. "1524",
  323. "3306",
  324. "3389",
  325. "5631",
  326. "6000",
  327. "6112",
  328. "8000",
  329. "8080",
  330. "12345" //这里你也可以自己定义要扫描的端口
  331. };
  332.   
  333. // 显示扫描开始的时间
  334. timenow = _strtime(timebuf);
  335. printf("\r\nPortScan Start Time: %s\r\n\n",timenow);

  336. // 计数器初始化.
  337. maxth = 0;
  338. scanok = 0;
  339. scannum = 0;
  340. searched = 0;

  341. // 计算要扫描的端口数量
  342. searchnum = hoststop - hoststart +1;
  343. if(xp == 3)
  344. searchnum = searchnum * 32;
  345. if(xp == 4)
  346. searchnum = searchnum * (endport - startport +1);

  347. // 端口扫描开始
  348. for (portip = hoststart; portip <= hoststop; portip ++, scannum ++)
  349. {
  350. // *.*.*.0和*.*.*.255 地址处理
  351. if ((portip % 256) == 0 || (portip % 256) == 255)
  352. {
  353.   if(xp == 3)
  354.   searchnum = searchnum - 32;
  355.   if(xp == 4)
  356.   searchnum = searchnum - (endport - startport +1);
  357.   scannum --;
  358.   playx();
  359.   continue;
  360. }
  361.   
  362. if(i > 11) i = 0;
  363. // 默认端口扫描
  364. // scan 192.168.0.1
  365. // scan 192.168.0.1-192.168.0.254
  366. if (xp == 3)
  367. {
  368.   for (sport = 0; sport < 32; sport ++, maxth ++, searched ++)
  369.   {
  370.   // 测试当前线程是否大于180
  371.   TestThread(180);
  372.   // 产生新的线程处理端口扫描
  373.   CWinThread * pthread = AfxBeginThread(portscan,LPVOID(atoi((char*)ports[sport])));
  374.   //延时
  375.   Sleep(120);
  376.   }
  377. }
  378.   
  379. // 自定义端口扫描
  380. // scan -p 21 192.168.0.1
  381. // scan -p 21-80 192.168.0.1-192.168.0.254
  382. if (xp == 4)
  383. { // 计算要扫描的端口
  384.   sport = endport - startport;
  385.   if(sport > 500 )
  386.   {
  387.   // 扫描自定义的端口
  388.   for(sport = startport; sport <= endport; sport ++, maxth ++, searched ++)
  389.   {
  390.    TestThread(2000);
  391.    // 产生新的线程处理端口扫描
  392.    CWinThread * pthread = AfxBeginThread(portscan, LPVOID(sport));
  393.    // 延时
  394.    Sleep(10);
  395.   }
  396.   }
  397.   else
  398.   {
  399.   // 扫描自定义的端口
  400.   for(sport = startport; sport <= endport; sport ++, maxth ++, searched ++)
  401.   {
  402.    // 测试当前线程是否大于250
  403.    TestThread(250);
  404.    // 产生新的线程处理端口扫描
  405.    CWinThread * pthread = AfxBeginThread(portscan, LPVOID(sport));
  406.    // 延时
  407.    Sleep(100);
  408.    playx();
  409.   }
  410.   }
  411. }
  412. }

  413. // 等待所有的线程结束
  414. WaitThreadEnd();

  415. // 显示端口扫描结束时间
  416. timenow = _strtime(timebuf);
  417. printf("\r\nPortScan End Time: %s", timenow);
  418. printf("\r\nScan %d Hosts completed. Open %d Ports!\r\n", scannum, scanok);
  419. }

再来一个连接测试代码:


/********************************************/
/****   作者::夕君                **/
/****   时间:2004.04.04                     **/
/****   北京金万维科技 **/
/*******************************************/
/*此函数实现判断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;


}
阅读(1937) | 评论(0) | 转发(5) |
给主人留下些什么吧!~~