一个简单的端口扫描程序
做一个简单的端口扫描程序
界面:
控件设置:
IDC_EDIT_ADDR 关联 CString m_strAddr
IDC_BOTTON_PORT_SCAN
IDC_LIST_TARGET 关联 CLISTBOX m_ListTarget 取消选中sort复选框
IDC_LIST_RESULT 关联 CLISTBOX m_ListResult 取消选中sort复选框
在主对话框类Port_ScanDlg.h 中添加
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")
在类Port_Scan.cpp 文件中加入需要扫描的端口数组和声明端口扫描线程入口函数:
UINT nPortArray[14]={13,15,21,25,80,110,135,137,139,445,1025,1433,3306,53}; //需要扫描的端口数组
DWORD WINAPI PortScanThreadProc(LPVOID pParam); //端口扫描线程入口函数
在类Port_ScanDl.cpp中加入以下代码,初始化网络环境和显示需要扫描的端口:
BOOL CPort_ScanDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
..........
// TODO: 在此添加额外的初始化代码
WSADATA wsadata;
WSAStartup(MAKEWORD(2,2),&wsadata); //启用socket
CString strPort;
for(int i=0;i<14;i++)
{
strPort.Format("%lu",nPortArray[i]); //将数字转化为字符串
m_ListTarget.AddString(strPort); //列表中加入端口扫描的任务显示
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
在类Port_ScanDlg.cpp成员函数OnBnClickedButtonPortScan()中实现按钮“扫描端口”功能。
void CPort_ScanDlg::OnBnClickedButtonPortScan()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE); //将控件的内容读入到相关联的变量中
if(m_strAddr.IsEmpty())
{
AfxMessageBox("请填写IP地址");
return;
}
HANDLE hThread=CreateThread(NULL,0,PortScanThreadProc,this,0,NULL); //开启端口扫描线程
CloseHandle(hThread);//关闭线程语句
GetDlgItem(IDC_BUTTON_PORT_SCAN)->EnableWindow(FALSE); //使得控件不可用
}
在在类Port_ScanDlg.cpp中实现扫描端口线程入口函数:
DWORD WINAPI PortScanThreadProc(LPVOID pParam)
{
CPort_ScanDlg *pDlg=(CPort_ScanDlg *)pParam;
sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.S_un.S_addr=inet_addr(pDlg->m_strAddr); //从字符串IP转化为32位IP
int nretval;
struct timeval tv;
DWORD lMode=1;
fd_set fdsock;
// SOCKET hSocket;
tv.tv_sec=2; //设置超时时间为2秒
tv.tv_usec=0;
//依次查看端口是否开放
for (int i=0;i<14;i++)
{
//创建套接字
SOCKET hSocket=socket(AF_INET,SOCK_STREAM,0);
if(hSocket==INVALID_SOCKET)continue;
//设置套接字为非阻塞型套接字
ioctlsocket(hSocket,FIONBIO,&lMode);
//清空fdsock 这个集合
FD_ZERO(&fdsock);
//将套接字装入fdsock集合
FD_SET(hSocket,&fdsock);
addr.sin_port=htons(nPortArray[i]);
//连接主机
nretval=connect(hSocket,(sockaddr *)&addr,sizeof(addr));
if(nretval==SOCKET_ERROR)
{
//select模型
nretval=select(0,NULL,&fdsock,NULL,&tv);
//当存在此端口,select()函数返回值大于0
if(nretval>0){
pDlg->SendMessage(WM_ADDPORT,0,(LPARAM)&nPortArray[i]);
}
}
else
{
pDlg->SendMessage(WM_ADDPORT,0,(LPARAM)&nPortArray[i]);
}
closesocket(hSocket); //关闭套接字
}
AfxMessageBox("端口扫描完成!");
pDlg->GetDlgItem(IDC_BUTTON_PORT_SCAN)->EnableWindow(TRUE);
return 0L;
}
最后实现 自定义消息WM_ADDPORT响应函数:LRESULT OnAddPort(WPARAM wParam,LPARAM lParam)
LRESULT CPort_ScanDlg::OnAddPort(WPARAM wParam,LPARAM lParam)
{
UINT nPort = *(UINT*)lParam;
CString strPort;
strPort.Format("%lu", nPort);
m_ListResult.AddString(strPort);
return 0L;
}