ScanPortDlg.cpp
上传用户:by888888
上传日期:2015-06-24
资源大小:42k
文件大小:13k
源码类别:

Telnet客户端

开发平台:

Visual C++

  1. // ScanPortDlg.cpp 
  2. //
  3. //作者 何嘉宁
  4. #include "stdafx.h"
  5. #include "ScanPort.h"
  6. #include "ScanPortDlg.h"
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. //线程返回的错误代码,调试用
  13. #define ERROR_CREATE_SOCKET -1L
  14. #define ERROR_MODIFY_FIONBIO -2L
  15. #define ERROR_SELECT -3L
  16. #define ERROR_SELECT_TIMEOUT -4L
  17. //线程发回的消息
  18. #define SCAN_THREAD WM_USER+100
  19. //线程发回的消息的wParam参数定义
  20. #define DOSCAN_FIND_PORT 1 //发现一个开放端口
  21. #define DOSCAN_END_PORT 2 //完成一个端口扫描
  22. #define STARTSCAN_COMPLETE 3 //完成所有扫描
  23. //
  24. #define MAX_SEPECIEFIED_PORTS 256 //对于扫描指定的端口的最大数
  25. //全局变量
  26. HWND g_hWnd = NULL; //处理消息的窗口句柄
  27. unsigned long g_ulAddr = INADDR_NONE; //扫描的主机地址
  28. DWORD g_dwTimeOut = 1000; //连接超时时间,以ms计
  29. bool g_bTerminate = false; //是否用户发出结束扫描的标志
  30. short g_nMaxThread = 200; //最大允许的扫描线程数,经试验不宜大于200
  31. short g_nThreadCount = 0; //当前正在扫描的进程数
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CAboutDlg dialog used for App About
  34. struct tag_PORTS
  35. {
  36. BOOL bSepecifiedPort;
  37. union
  38. {
  39. struct
  40. {
  41. unsigned short iStartPort;
  42. unsigned short iEndPort;
  43. };
  44. struct
  45. {
  46. unsigned short nCount;
  47. unsigned short nArrOfPorts[MAX_SEPECIEFIED_PORTS];
  48. };
  49. };
  50. };
  51. bool IsIpString(const char* pszHostOrIp)
  52. {
  53. if (strlen(pszHostOrIp) > 15)
  54. {
  55. return false;
  56. }
  57. //创建一个输入字符的副本,防止被修改
  58. char szHostOrIpCopy[16];
  59. strcpy(szHostOrIpCopy, pszHostOrIp);
  60. int nPart = 0;
  61. char* pszPart = strtok(szHostOrIpCopy, ".");
  62. while (pszPart != NULL)
  63. {
  64. for (unsigned int i=0; i<strlen(pszPart); i++)
  65. {
  66. if (pszPart[i]>'9' || pszPart[i]<'0')
  67. {
  68. return false;
  69. }
  70. }
  71. if (unsigned int(atoi(pszPart)) > 255)
  72. {
  73. return false;
  74. }
  75. nPart++;
  76. pszPart = strtok(NULL, ".");
  77. }
  78. return nPart == 4;
  79. }
  80. unsigned long GetAddr(const char* pszHostOrIp)
  81. {
  82. if (*pszHostOrIp == '')
  83. {
  84. return inet_addr("127.0.0.1");
  85. }
  86. if (IsIpString(pszHostOrIp))
  87. {
  88. return inet_addr(pszHostOrIp);
  89. }
  90. hostent* pHostent = gethostbyname(pszHostOrIp);
  91. if (pHostent == NULL)
  92. {
  93. return INADDR_NONE;
  94. }
  95. return  (*(unsigned long*)*pHostent->h_addr_list);
  96. }
  97. DWORD WINAPI DoScanPort(LPVOID lpParam)
  98. {
  99. DWORD dwRet;
  100. short nPort = *(short*) lpParam;
  101. delete lpParam;
  102. SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
  103. if(sock == INVALID_SOCKET)
  104. {
  105. AfxMessageBox("创建套接字失败!");
  106. dwRet = ERROR_CREATE_SOCKET;
  107. }
  108. else
  109. {
  110. unsigned long flag = 1; 
  111. if ((ioctlsocket(sock, FIONBIO, &flag) != 0))
  112. {
  113. AfxMessageBox("未能改为非阻塞模式!");
  114. dwRet = ERROR_MODIFY_FIONBIO;
  115. }
  116. else
  117. {
  118. sockaddr_in severAddr;
  119. severAddr.sin_family = AF_INET;
  120. severAddr.sin_port = htons(nPort); 
  121. severAddr.sin_addr.S_un.S_addr = g_ulAddr;
  122. connect(sock, (sockaddr*)&severAddr, sizeof(severAddr));
  123. struct fd_set mask;
  124. FD_ZERO(&mask);
  125. FD_SET(sock, &mask);
  126. struct timeval timeout;
  127. timeout.tv_sec = g_dwTimeOut / 1000;
  128. timeout.tv_usec = g_dwTimeOut % 1000;
  129. switch(select(0, NULL, &mask, NULL, &timeout))
  130. {
  131. case -1:
  132. dwRet = ERROR_SELECT;
  133. break;
  134. case 0:
  135. dwRet = ERROR_SELECT_TIMEOUT;
  136. break;
  137. default:
  138. dwRet = ERROR_SUCCESS;
  139. };
  140. }
  141. closesocket(sock);
  142. }
  143. g_nThreadCount --;
  144. if (dwRet == ERROR_SUCCESS)
  145. {
  146. ::SendMessage(g_hWnd, SCAN_THREAD, DOSCAN_FIND_PORT, nPort);
  147. }
  148. else
  149. {
  150. ::SendMessage(g_hWnd, SCAN_THREAD, DOSCAN_END_PORT, nPort);
  151. }
  152. return dwRet;
  153. }
  154. DWORD WINAPI StartScan(LPVOID lpParam)
  155. {
  156. tag_PORTS* pScanParam = (tag_PORTS*)lpParam;
  157. DWORD dwThreadId;
  158. unsigned short i;
  159. if (pScanParam->bSepecifiedPort)
  160. {
  161. for(i=0; i<=pScanParam->nCount; i++)
  162. {
  163. if (g_bTerminate)
  164. {
  165. break; //用户已发出结束扫描命令
  166. }
  167. while(g_nThreadCount >= g_nMaxThread)
  168. {
  169. Sleep(10);
  170. }
  171. if (CreateThread(NULL, 0, DoScanPort, (LPVOID)new short(pScanParam->nArrOfPorts[i]), 0, &dwThreadId) != NULL)
  172. {
  173. g_nThreadCount ++;
  174. }
  175. }
  176. }
  177. else
  178. {
  179. for(i=pScanParam->iStartPort; i<=pScanParam->iEndPort; i++)
  180. {
  181. if (g_bTerminate)
  182. {
  183. break; //用户已发出结束扫描命令
  184. }
  185. while(g_nThreadCount >= g_nMaxThread)
  186. {
  187. Sleep(10);
  188. }
  189. if (CreateThread(NULL, 0, DoScanPort, (LPVOID)new short(i), 0, &dwThreadId) != NULL)
  190. {
  191. g_nThreadCount ++;
  192. }
  193. }
  194. }
  195. //等待各端口扫描线程结束
  196. while (g_nThreadCount > 0)
  197. {
  198. Sleep(50);
  199. }
  200. ::SendMessage(g_hWnd, SCAN_THREAD, STARTSCAN_COMPLETE, 0);
  201. delete pScanParam;
  202. return ERROR_SUCCESS;
  203. }
  204. class CAboutDlg : public CDialog
  205. {
  206. public:
  207. CAboutDlg();
  208. // Dialog Data
  209. //{{AFX_DATA(CAboutDlg)
  210. enum { IDD = IDD_ABOUTBOX };
  211. //}}AFX_DATA
  212. // ClassWizard generated virtual function overrides
  213. //{{AFX_VIRTUAL(CAboutDlg)
  214. protected:
  215. virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
  216. //}}AFX_VIRTUAL
  217. // Implementation
  218. protected:
  219. //{{AFX_MSG(CAboutDlg)
  220. //}}AFX_MSG
  221. DECLARE_MESSAGE_MAP()
  222. };
  223. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  224. {
  225. //{{AFX_DATA_INIT(CAboutDlg)
  226. //}}AFX_DATA_INIT
  227. }
  228. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  229. {
  230. CDialog::DoDataExchange(pDX);
  231. //{{AFX_DATA_MAP(CAboutDlg)
  232. //}}AFX_DATA_MAP
  233. }
  234. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  235. //{{AFX_MSG_MAP(CAboutDlg)
  236. // No message handlers
  237. //}}AFX_MSG_MAP
  238. END_MESSAGE_MAP()
  239. /////////////////////////////////////////////////////////////////////////////
  240. // CScanPortDlg dialog
  241. CScanPortDlg::CScanPortDlg(CWnd* pParent /*=NULL*/)
  242. : CDialog(CScanPortDlg::IDD, pParent)
  243. {
  244. //{{AFX_DATA_INIT(CScanPortDlg)
  245. m_csHostOrIp = _T("");
  246. m_bIsSpecifiedPort = FALSE;
  247. m_nMaxThread = 200;
  248. m_iStartPort = 1;
  249. m_dwTimeOut = 1000;
  250. m_iEndPort = 1024;
  251. //}}AFX_DATA_INIT
  252. // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
  253. m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
  254. m_hThread = NULL;
  255. }
  256. void CScanPortDlg::DoDataExchange(CDataExchange* pDX)
  257. {
  258. CDialog::DoDataExchange(pDX);
  259. //{{AFX_DATA_MAP(CScanPortDlg)
  260. DDX_Control(pDX, IDC_SPECIFIED_PORTS, m_ctrSpecifiedPorts);
  261. DDX_Control(pDX, IDC_IS_SPECIFIED_PORT, m_ctrCheck);
  262. DDX_Control(pDX, IDC_TREE, m_ctrResultTree);
  263. DDX_Control(pDX, IDC_SCAN, m_ctrBeginScan);
  264. DDX_Text(pDX, IDC_HOST_OR_IP, m_csHostOrIp);
  265. DDX_Check(pDX, IDC_IS_SPECIFIED_PORT, m_bIsSpecifiedPort);
  266. DDX_Text(pDX, IDC_MAX_THREAD, m_nMaxThread);
  267. DDV_MinMaxUInt(pDX, m_nMaxThread, 50, 200);
  268. DDX_Text(pDX, IDC_START_PORT, m_iStartPort);
  269. DDX_Text(pDX, IDC_TIME_OUT, m_dwTimeOut);
  270. DDV_MinMaxDWord(pDX, m_dwTimeOut, 0, 100000);
  271. DDX_Text(pDX, IDC_END_PORT, m_iEndPort);
  272. //}}AFX_DATA_MAP
  273. }
  274. BEGIN_MESSAGE_MAP(CScanPortDlg, CDialog)
  275. //{{AFX_MSG_MAP(CScanPortDlg)
  276. ON_WM_SYSCOMMAND()
  277. ON_WM_PAINT()
  278. ON_WM_QUERYDRAGICON()
  279. ON_BN_CLICKED(IDC_IS_SPECIFIED_PORT, OnIsSpecifiedPort)
  280. ON_BN_CLICKED(IDC_SCAN, OnScan)
  281. ON_WM_DESTROY()
  282. ON_WM_TIMER()
  283. ON_EN_CHANGE(IDC_SPECIFIED_PORTS, OnChangeSpecifiedPorts)
  284. //}}AFX_MSG_MAP
  285. ON_MESSAGE(SCAN_THREAD, OnScanThread)
  286. END_MESSAGE_MAP()
  287. /////////////////////////////////////////////////////////////////////////////
  288. // CScanPortDlg message handlers
  289. BOOL CScanPortDlg::OnInitDialog()
  290. {
  291. CDialog::OnInitDialog();
  292. // Add "About..." menu item to system menu.
  293. // IDM_ABOUTBOX must be in the system command range.
  294. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
  295. ASSERT(IDM_ABOUTBOX < 0xF000);
  296. CMenu* pSysMenu = GetSystemMenu(FALSE);
  297. if (pSysMenu != NULL)
  298. {
  299. CString strAboutMenu;
  300. strAboutMenu.LoadString(IDS_ABOUTBOX);
  301. if (!strAboutMenu.IsEmpty())
  302. {
  303. pSysMenu->AppendMenu(MF_SEPARATOR);
  304. pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
  305. }
  306. }
  307. // Set the icon for this dialog.  The framework does this automatically
  308. //  when the application's main window is not a dialog
  309. SetIcon(m_hIcon, TRUE); // Set big icon
  310. SetIcon(m_hIcon, FALSE); // Set small icon
  311. // TODO: Add extra initialization here
  312. m_pProgressCtrl = (CProgressCtrl*)GetDlgItem(IDC_PROGRESS1);
  313. m_pProgressCtrl->SetStep(1);
  314. ReadDefaultPorts();
  315. m_csHostOrIp = "localhost";
  316. UpdateData(false);
  317. WSADATA wsaData;
  318. BOOL ret = WSAStartup(MAKEWORD(2,2), &wsaData);
  319. if(ret != 0)
  320. {
  321. MessageBox("初始化网络协议失败!");
  322. return -1;
  323. }
  324. return TRUE;  // return TRUE  unless you set the focus to a control
  325. }
  326. void CScanPortDlg::OnSysCommand(UINT nID, LPARAM lParam)
  327. {
  328. if ((nID & 0xFFF0) == IDM_ABOUTBOX)
  329. {
  330. CAboutDlg dlgAbout;
  331. dlgAbout.DoModal();
  332. }
  333. else
  334. {
  335. CDialog::OnSysCommand(nID, lParam);
  336. }
  337. }
  338. // If you add a minimize button to your dialog, you will need the code below
  339. //  to draw the icon.  For MFC applications using the document/view model,
  340. //  this is automatically done for you by the framework.
  341. void CScanPortDlg::OnPaint() 
  342. {
  343. if (IsIconic())
  344. {
  345. CPaintDC dc(this); // device context for painting
  346. SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
  347. // Center icon in client rectangle
  348. int cxIcon = GetSystemMetrics(SM_CXICON);
  349. int cyIcon = GetSystemMetrics(SM_CYICON);
  350. CRect rect;
  351. GetClientRect(&rect);
  352. int x = (rect.Width() - cxIcon + 1) / 2;
  353. int y = (rect.Height() - cyIcon + 1) / 2;
  354. // Draw the icon
  355. dc.DrawIcon(x, y, m_hIcon);
  356. }
  357. else
  358. {
  359. CDialog::OnPaint();
  360. }
  361. }
  362. HCURSOR CScanPortDlg::OnQueryDragIcon()
  363. {
  364. return (HCURSOR) m_hIcon;
  365. }
  366. void CScanPortDlg::OnIsSpecifiedPort() 
  367. {
  368. BOOL bCheck = m_ctrCheck.GetCheck();
  369. m_ctrSpecifiedPorts.EnableWindow(bCheck);
  370. }
  371. void CScanPortDlg::OnScan() 
  372. {
  373. if (m_hThread == NULL)
  374. {
  375. UpdateData();
  376. if ((g_ulAddr = GetAddr(m_csHostOrIp)) == INADDR_NONE)
  377. {
  378. AfxMessageBox("无法找到主机");
  379. return;
  380. }
  381. m_nHasComplete = 0;
  382. m_dwPercentSeconds = 0;
  383. m_pProgressCtrl->SetPos(0);
  384. m_hParentTree = m_ctrResultTree.InsertItem(m_csHostOrIp+CTime::GetCurrentTime().Format("---扫描时间%H:%M:%S"));
  385. g_bTerminate = false;
  386. g_dwTimeOut = m_dwTimeOut;
  387. g_hWnd = m_hWnd;
  388. g_nMaxThread = m_nMaxThread;
  389. g_nThreadCount = 0;
  390. tag_PORTS* pScanParam = new tag_PORTS;
  391. pScanParam->bSepecifiedPort = m_bIsSpecifiedPort;
  392. if (m_bIsSpecifiedPort)
  393. {
  394. //指定端口
  395. short nCount = 0;
  396. char buff[10];
  397. for(int i=0; i<m_ctrSpecifiedPorts.GetLineCount(); i++)
  398. {
  399. int len = m_ctrSpecifiedPorts.GetLine(i, buff, 9);
  400. if (len != 0)
  401. {
  402. buff[len] = '';
  403. pScanParam->nArrOfPorts[nCount++]= atoi(buff);
  404. }
  405. }
  406. pScanParam->nCount = nCount;
  407. m_pProgressCtrl->SetRange(0, pScanParam->nCount);
  408. }
  409. else
  410. {
  411. pScanParam->iStartPort = m_iStartPort;
  412. pScanParam->iEndPort = m_iEndPort;
  413. m_pProgressCtrl->SetRange(0, m_iEndPort-m_iStartPort+1);
  414. }
  415. DWORD dwThreadId;
  416. m_hThread = CreateThread(NULL, 0, StartScan, (LPVOID)pScanParam, 0, &dwThreadId);
  417. m_ctrBeginScan.SetWindowText("结束扫描");
  418. SetTimer(1, 100, NULL);
  419. }
  420. else if (!g_bTerminate)
  421. {
  422. g_bTerminate = TRUE;
  423. m_ctrBeginScan.SetWindowText("正在结束...");
  424. }
  425. }
  426. void CScanPortDlg::OnDestroy() 
  427. {
  428. TerminateThread(m_hThread, 0);
  429. m_hThread = NULL;
  430. KillTimer(1);
  431. SaveDefaultPorts();
  432. WSACleanup();
  433. CDialog::OnDestroy();
  434. }
  435. void CScanPortDlg::OnTimer(UINT nIDEvent) 
  436. {
  437. if (nIDEvent == 1)
  438. {
  439. CString s;
  440. m_dwPercentSeconds++;
  441. s.Format("用时%3d.%1d秒", m_dwPercentSeconds/10, m_dwPercentSeconds%10);
  442. GetDlgItem(IDC_TIME)->SetWindowText(s);
  443. m_pProgressCtrl->SetPos(m_nHasComplete);
  444. }
  445. CDialog::OnTimer(nIDEvent);
  446. }
  447. void CScanPortDlg::OnScanThread(WPARAM wParam, LPARAM lParam)
  448. {
  449. char buff[10];
  450. switch(wParam)
  451. {
  452. case DOSCAN_FIND_PORT:
  453. sprintf(buff, "%d", short(lParam));
  454. m_ctrResultTree.InsertItem(buff, m_hParentTree);
  455. m_ctrResultTree.Expand(m_hParentTree, TVE_EXPAND);
  456. case DOSCAN_END_PORT:
  457. m_nHasComplete++;
  458. break;
  459. case STARTSCAN_COMPLETE:
  460. m_hThread = NULL;
  461. m_ctrBeginScan.SetWindowText("开始扫描");
  462. KillTimer(1);
  463. AfxMessageBox("本次扫描结束");
  464. break;
  465. default:
  466. break;
  467. }
  468. }
  469. BOOL CScanPortDlg::PreTranslateMessage(MSG* pMsg) 
  470. {
  471. //处理回车键
  472. if (pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE))
  473. {
  474. return 0;
  475. }
  476. return CDialog::PreTranslateMessage(pMsg);
  477. }
  478. void CScanPortDlg::ReadDefaultPorts()
  479. {
  480. try
  481. {
  482. CStdioFile f("DefaultPorts.txt", CFile::modeRead|CFile::typeText);
  483. CString s, ss;
  484. while (f.ReadString(ss))
  485. {
  486. s += ss;
  487. s += "rn";
  488. }
  489. GetDlgItem(IDC_SPECIFIED_PORTS)->SetWindowText(s);
  490. f.Close();
  491. }
  492. catch(...)
  493. {
  494. CString s = "13rn37rn80rn123rn135rn139rn489rn1002";
  495. GetDlgItem(IDC_SPECIFIED_PORTS)->SetWindowText(s);
  496. }
  497. }
  498. void CScanPortDlg::SaveDefaultPorts()
  499. {
  500. CStdioFile f("DefaultPorts.txt", CFile::modeCreate|CFile::modeWrite|CFile::typeText);
  501. char buff[10];
  502. for(int i=0; i<m_ctrSpecifiedPorts.GetLineCount(); i++)
  503. {
  504. int len = m_ctrSpecifiedPorts.GetLine(i, buff, 9);
  505. if (len != 0)
  506. {
  507. buff[len] = '';
  508. f.WriteString(buff);
  509. f.WriteString("rn");
  510. }
  511. }
  512. f.Close();
  513. }
  514. void CScanPortDlg::OnChangeSpecifiedPorts() 
  515. {
  516. // TODO: If this is a RICHEDIT control, the control will not
  517. // send this notification unless you override the CDialog::OnInitDialog()
  518. // function and call CRichEditCtrl().SetEventMask()
  519. // with the ENM_CHANGE flag ORed into the mask.
  520. // TODO: Add your control notification handler code here
  521. }