www.pudn.com > NetScan.rar > NetScanView.cpp


// NetScanView.cpp : implementation of the CNetScanView class 
// 
 
#include "stdafx.h" 
#include "NetScan.h" 
#include "NetScanDoc.h" 
#include "NetScanView.h" 
#include "Ping.h" 
#include  
#include "Afxsock.h" 
 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
extern volatile BOOL g_threadContral;//线程停止的标准,true为运行,false为停止; 
//-------端口扫描线程 声明-------- 
//CCriticalSection global_criticalsection; 
UINT PortScanThread(LPVOID pParam); 
struct _PORTSCANTHREADPARAM 
{ 
	unsigned int m_BBeginSegAddress;		//该线程扫描的起始IP地址 
	unsigned int m_BEndSegAddress;		//该线程扫描的终止IP地址 
	unsigned int timeout;	//超时时间 
	CNetScanView *const dlg;			//对话框指针 
	_PORTSCANTHREADPARAM(CNetScanView *d):dlg(d)//构造函数 
	{ 
		//dlg->SetWindowText("扫描端口!"); 
	} 
}; 
_PORTSCANTHREADPARAM *param2=NULL;//全局的线程参数对象 
volatile BOOL g_bStop;//线程停止的标准,true为运行,false为停止; 
 
 
///////////////////////////////////////////////////////////////////////////// 
// CNetScanView 
 
IMPLEMENT_DYNCREATE(CNetScanView, CFormView) 
 
BEGIN_MESSAGE_MAP(CNetScanView, CFormView) 
	//{{AFX_MSG_MAP(CNetScanView) 
	ON_WM_CLOSE() 
	ON_BN_CLICKED(IDC_BTN_START, OnBtnStart) 
	//}}AFX_MSG_MAP 
	// Standard printing commands 
	ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint) 
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview) 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CNetScanView construction/destruction 
 
CNetScanView::CNetScanView() 
	: CFormView(CNetScanView::IDD) 
{ 
	//{{AFX_DATA_INIT(CNetScanView) 
		// NOTE: the ClassWizard will add member initialization here 
	//}}AFX_DATA_INIT 
	// TODO: add construction code here 
	m_run=0; 
	m_timeout=100; 
	for(int i=0;i<6;i++) 
		m_Port[i]=0; 
	m_uThreadNum=1; 
} 
 
CNetScanView::~CNetScanView() 
{ 
} 
 
void CNetScanView::DoDataExchange(CDataExchange* pDX) 
{ 
	CFormView::DoDataExchange(pDX); 
	//{{AFX_DATA_MAP(CNetScanView) 
	DDX_Control(pDX, IDC_LIST1, m_ctrlList); 
	//}}AFX_DATA_MAP 
} 
 
BOOL CNetScanView::PreCreateWindow(CREATESTRUCT& cs) 
{ 
	// TODO: Modify the Window class or styles here by modifying 
	//  the CREATESTRUCT cs 
 
	return CFormView::PreCreateWindow(cs); 
} 
 
void CNetScanView::OnInitialUpdate() 
{ 
	CFormView::OnInitialUpdate(); 
	GetParentFrame()->RecalcLayout(); 
	ResizeParentToFit(); 
 
	if(AfxSocketInit(NULL)==FALSE)//初始化Socket 
	{ 
		AfxMessageBox("Sorry,socket 失败!"); 
	} 
	g_bStop=true; 
	g_threadContral=false; 
	param2 = new _PORTSCANTHREADPARAM(this); 
	SetUI(); 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CNetScanView printing 
 
BOOL CNetScanView::OnPreparePrinting(CPrintInfo* pInfo) 
{ 
	// default preparation 
	return DoPreparePrinting(pInfo); 
} 
 
void CNetScanView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add extra initialization before printing 
} 
 
void CNetScanView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add cleanup after printing 
} 
 
void CNetScanView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/) 
{ 
	// TODO: add customized printing code here 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CNetScanView diagnostics 
 
#ifdef _DEBUG 
void CNetScanView::AssertValid() const 
{ 
	CFormView::AssertValid(); 
} 
 
void CNetScanView::Dump(CDumpContext& dc) const 
{ 
	CFormView::Dump(dc); 
} 
 
CNetScanDoc* CNetScanView::GetDocument() // non-debug version is inline 
{ 
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CNetScanDoc))); 
	return (CNetScanDoc*)m_pDocument; 
} 
#endif //_DEBUG 
 
///////////////////////////////////////////////////////////////////////////// 
// CNetScanView message handlers 
 
//DEL void CNetScanView::OnButton1()  
//DEL { 
//DEL  
//DEL } 
 
void CNetScanView::StartPing() 
{//运行ping程序 
	if(g_threadContral) 
	{ 
		((CButton *)GetDlgItem(IDC_BTN_START))->SetWindowText("开始ping"); 
		g_threadContral=false; 
		return; 
	}else 
	{ 
		((CButton *)GetDlgItem(IDC_BTN_START))->SetWindowText("停止ping"); 
		g_threadContral=true; 
		//开始循环ping地址 
		CPing * pinger=new CPing(this); 
		//设置Ping参数 
		pinger->SetConfigure(m_BBeginAddress,m_BEndAddress,m_pingNumber,m_timeout); 
		//开始Ping 
		pinger->ping(); 
		return; 
	} 
} 
 
void CNetScanView::StartPortScan() 
{//运行端口扫描程序 
	//开启一个新的扫描线程 
	if(g_bStop) 
	{ 
		((CButton *)GetDlgItem(IDC_BTN_START))->SetWindowText("停止扫描"); 
		g_bStop=false; 
		param2->m_BBeginSegAddress=m_BBeginAddress; 
		param2->m_BEndSegAddress=m_BEndAddress; 
		param2->timeout=m_timeout; 
		AfxBeginThread(PortScanThread,(LPVOID)param2); 
	}else 
	{ 
		((CButton *)GetDlgItem(IDC_BTN_START))->SetWindowText("开始扫描"); 
		g_bStop=true; 
	} 
} 
 
void CNetScanView::OnClose()  
{ 
	// TODO: Add your message handler code here and/or call default 
	 
	CFormView::OnClose(); 
 
} 
 
void CNetScanView::OnBtnStart()  
{ 
	switch(m_run) 
	{ 
	case 0: 
		break; 
	case PING: 
		StartPing(); 
		break; 
	case PORTSCAN: 
		StartPortScan(); 
		break; 
	default: 
		break; 
	}	 
} 
 
void CNetScanView::SetUI() 
{//设置用户界面 
	int	i=0;//子项索引 
	LV_COLUMN lvcol; 
	lvcol.mask=LVCF_FMT|LVCF_SUBITEM|LVCF_TEXT|LVCF_WIDTH; 
	lvcol.fmt=LVCFMT_CENTER;//居中 
	m_ctrlList.DeleteAllItems(); 
 
	if(m_run==0) 
	{ 
		((CButton *)GetDlgItem(IDC_BTN_START))->EnableWindow(false); 
		return; 
	} 
	if(m_run==PING) 
	{ 
		while(m_ctrlList.DeleteColumn(0))//删除所有列 
		{ 
		} 
		//设置list控件的表头 
		i=0; 
		lvcol.pszText="能ping通的IP地址";//ListCtrl第1项 
		lvcol.iSubItem=i; 
		lvcol.cx=120; 
		m_ctrlList.InsertColumn(i++,&lvcol); 
 
		lvcol.pszText="返回时间";//ListCtrl第2项 
		lvcol.iSubItem=i; 
		lvcol.cx=70; 
		m_ctrlList.InsertColumn(i++,&lvcol); 
		/* 
		lvcol.pszText="seq";//ListCtrl第3项 
		lvcol.iSubItem=i; 
		lvcol.cx=70; 
		m_ctrlList.InsertColumn(i++,&lvcol); 
		*/ 
		return; 
	} 
 
	if(m_run==PORTSCAN) 
	{ 
		while(m_ctrlList.DeleteColumn(0))//删除所有列 
		{ 
		} 
		//设置list控件的表头 
		i=0; 
		lvcol.pszText="IP地址"; 
		lvcol.iSubItem=i; 
		lvcol.cx=120; 
		m_ctrlList.InsertColumn(i++,&lvcol); 
		 
		lvcol.cx=80; 
		if(m_Port[0]==80)//http 
		{ 
			lvcol.pszText="HTTP(80)"; 
			lvcol.iSubItem=i; 
			m_ctrlList.InsertColumn(i++,&lvcol); 
		} 
		if(m_Port[1]==21)//ftp 
		{ 
			lvcol.pszText="FTP(21)"; 
			lvcol.iSubItem=i; 
			m_ctrlList.InsertColumn(i++,&lvcol); 
		} 
		if(m_Port[2]==53)//dns 
		{ 
			lvcol.pszText="DNS(53)"; 
			lvcol.iSubItem=i; 
			m_ctrlList.InsertColumn(i++,&lvcol); 
		} 
		if(m_Port[3]==25)//smtp 
		{ 
			lvcol.pszText="SMTP(25)"; 
			lvcol.iSubItem=i; 
			m_ctrlList.InsertColumn(i++,&lvcol); 
		} 
		if(m_Port[4]==110)//pop3 
		{ 
			lvcol.pszText="POP3(110)"; 
			lvcol.iSubItem=i; 
			m_ctrlList.InsertColumn(i++,&lvcol); 
		}if(m_Port[5]==161)//snmp 
		{ 
			lvcol.pszText="SNMP(161)"; 
			lvcol.iSubItem=i; 
			m_ctrlList.InsertColumn(i++,&lvcol); 
		} 
		return; 
	} 
} 
 
 
/*------------端口扫描技术------------------ 
 * TCP connect() 扫描  
 *这是最基本的TCP扫描。操作系统提供的connect()系统调用,用来与每一个感兴趣的目标计算机的端口进行连接。 
 *如果端口处于侦听状态,那么connect()就能成功。否则,这个端口是不能用的,即没有提供服务。 
 *这个技术最大的优点是,不需要任何权限。系统中的任何用户都有权利使用这个调用。 
 *另一个好处就是速度。如果对每个目标端口以线性的方式,使用单独的connect()调用, 
 *那么将会花费相当长的时间,你可以通过同时打开多个套接字,从而加速扫描。 
 *使用非阻塞I/O允许你设置一个低的时间用尽周期,同时观察多个套接字。 
 *但这种方法的缺点是很容易被发觉,并且被过滤掉。 
 *目标计算机的logs文件会显示一连串的连接和连接是出错的服务消息,并且能很快的使它关闭。  
 *-------------------------------------*/ 
 
//----------端口扫描函数------------ 
UINT PortScanThread(LPVOID pParam) 
{ 
	_PORTSCANTHREADPARAM* param=(_PORTSCANTHREADPARAM*)pParam; 
	ASSERT(pParam); 
	CNetScanView *dlg=param->dlg; 
	int currentip[4]; 
	unsigned int timeout=param->timeout; 
	//UINT port; 
	CString ip; 
	CString result; 
	unsigned int b,e,c; 
	//将4个BYTE的地址转换成一个unsigned int型的地址,方便之后的操作 
	b=param->m_BBeginSegAddress; 
	e=param->m_BEndSegAddress; 
	//扫描每个IP地址 
	for(c=b;c<=e;c++) 
	{ 
		if(g_bStop)//判断是否需要退出扫描 
		{ 
			break; 
		} 
		currentip[0]=(c&(255<<24))>>24; 
		currentip[1]=(c&(255<<16))>>16; 
		currentip[2]=(c&(255<<8))>>8; 
		currentip[3]=c&255; 
		//在将地址转换成一个字符串 
		ip.Format("%d.%d.%d.%d",currentip[0],currentip[1],currentip[2],currentip[3]); 
		result=""; 
		dlg->SetDlgItemText(IDC_S,"开始扫描 "+ip); 
		//扫描每个端口 
		BOOL tempPort[6];//存储扫描后端口的状态,端口开放为true,关闭为false 
		for(int i=0;i<6;i++) 
		{	 
			if(g_bStop)//判断是否需要退出扫描 
			{ 
				break; 
			} 
			tempPort[i]=false; 
			if(dlg->m_Port[i]!=0) 
			{ 
				//开启socket正是扫描 
				CSocket socket; 
				//创建socket 
				if(socket.Create(0,SOCK_STREAM)==FALSE)	 
				{ 
					int error1=socket.GetLastError(); 
					dlg->SetDlgItemText(IDC_S,"创建socket错误!"); 
					//AfxMessageBox("socket create error!"); 
					return 0; 
				} 
				/* 
				//设置发送超时				 
				if(setsockopt(socket,SOL_SOCKET,SO_SNDTIMEO, (char *)&timeout, sizeof(timeout))) 
				{ 
					int error2=socket.GetLastError(); 
					result.Format("%d",error2); 
					dlg->SetDlgItemText(IDC_S,"设置发送Timeout错误!错误号="+result); 
					return 0; 
				} 
				//设置接收超时 
				if(setsockopt(socket,SOL_SOCKET,SO_RCVTIMEO,(char *)&timeout, sizeof(timeout))) 
				{ 
					int error3=socket.GetLastError(); 
					result.Format("%d",error3); 
					dlg->SetDlgItemText(IDC_S,"设置接收Timeout错误!错误号="+result); 
					return 0; 
				} 
				*/ 
				result.Format("%d",dlg->m_Port[i]); 
				result="正在扫描:"+ip+" 端口:"+result; 
				 
				if(socket.Connect(ip,dlg->m_Port[i])==FALSE) //连接对方 
				{ 
					int error2=socket.GetLastError(); 
					TRACE("\n连接错误号:%d",error2); 
					switch(error2) 
					{	 
						case 10060: 
							dlg->SetDlgItemText(IDC_S,result+"  连接超时!"); 
							break; 
						case 10061: 
							dlg->SetDlgItemText(IDC_S,result+"  强行拒绝连接!"); 
							break; 
						default: 
							dlg->SetDlgItemText(IDC_S,result+"  连接失败!"); 
							break; 
					} 
					socket.Close(); 
					continue; 
				} 
				else{ 
					dlg->SetDlgItemText(IDC_S,result+"  连接成功!"); 
					socket.Close(); 
					tempPort[i]=true; 
				} 
				/* 
				//发送数据 
				if(socket.SendTo("hello",6,dlg->m_Port[i],ip)==SOCKET_ERROR) 
				{ 
					TRACE("%d\n",socket.GetLastError( )); 
					dlg->SetDlgItemText(IDC_S,result+"  连接失败!"); 
					socket.Close(); 
					continue; 
				}else 
				{ 
					dlg->SetDlgItemText(IDC_S,result+"  连接成功!"); 
					socket.Close(); 
					tempPort[i]=true; 
				} 
				//接收对方该端口的反馈信息 
				char buffer[256]; 
				memset(buffer,'\0',256); 
				if(socket.Receive(buffer,256,0)==SOCKET_ERROR) 
				{ 
					dlg->SetDlgItemText(IDC_S,result+"  关闭!"); 
					socket.Close(); 
					continue; 
				}else 
				{ 
					dlg->SetDlgItemText(IDC_S,result+"  开放!"); 
					socket.Close(); 
					tempPort[i]=true; 
					continue; 
				} 
				*/ 
 
			} 
		} 
		//在列表控件里显示结果数据 
		if(true) 
		{	 
			if(tempPort[0]||tempPort[1]||tempPort[2]|| 
				tempPort[3]||tempPort[4]||tempPort[5]) 
			{ 
				int isub=0; 
				int iPos=0; 
				LV_ITEM lvitem1; 
				lvitem1.mask=LVIF_TEXT; 
				lvitem1.iItem=1; 
				lvitem1.iSubItem=isub++; 
				lvitem1.pszText=ip.GetBuffer(16); 
				iPos=dlg->m_ctrlList.InsertItem(&lvitem1);//返回表项插入后的索引号 
				for(int j=0;j<6;j++) 
					if(dlg->m_Port[j]!=0) 
						if(tempPort[j]) 
						{ 
							lvitem1.iItem=iPos; 
							lvitem1.iSubItem=isub++; 
							lvitem1.pszText=_T("开启"); 
							dlg->m_ctrlList.SetItem(&lvitem1);//返回表项插入后的索引号 
						} 
						else 
						{ 
							lvitem1.iItem=iPos; 
							lvitem1.iSubItem=isub++; 
							lvitem1.pszText=_T("关闭"); 
							dlg->m_ctrlList.SetItem(&lvitem1);//返回表项插入后的索引号 
						} 
			} 
		} 
	} 
	dlg->SetDlgItemText(IDC_S,"结束扫描 "); 
	((CButton *)dlg->GetDlgItem(IDC_BTN_START))->SetWindowText("开始扫描"); 
	g_bStop=true; 
	return 0; 
}