www.pudn.com > NetScan.rar > Ping.cpp
// Ping.cpp: implementation of the CPing class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "Ping.h" #include "NetScanView.h" #include#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif //----------线程------------------- CCriticalSection global_criticalsection;//临界区变量 UINT PingThreadProc(LPVOID pParam); //线程函数的声明 struct _PINGTHREADPARAM //Ping线程参数 { unsigned int addr_begin; //线程扫描的起始IP地址 unsigned int addr_end; //线程扫描的结束IP地址 CPing *const pPing; _PINGTHREADPARAM(CPing *d):pPing(d)//构造函数 { } }; volatile BOOL g_threadContral;//线程停止的标准,true为运行,false为停止; _PINGTHREADPARAM *param=NULL;//全局的线程参数对象 ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CPing::CPing(CView *pParent /*NULL*/) { m_pView=(CNetScanView *)pParent; //初始化ICMP包 icmp_data=NULL; seq_no=0; recvbuf=NULL; m_bRecordRout=FALSE; lpdest=NULL; datasize=DEF_PACKET_SIZE; m_pingNumber=1; //初始化socket WSADATA wsaData; if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0) { AfxMessageBox("Sorry,you cannot load socket dll!"); return; } m_hSocket=INVALID_SOCKET; } CPing::~CPing() { } void CPing::SetConfigure(unsigned int begin, unsigned int end,int pingNumber,int timeout,BOOL recordrout, int size) {//设置Ping参数 m_bRecordRout = recordrout; datasize = size; m_addrBegin=begin; m_addrEnd=end; //lpdest=host; m_pingNumber=pingNumber; m_timeout=timeout; } void CPing::DecodeIPOptions(char *buf,int bytes) {//解析IP可选参数 IpOptionHeader *ipopt = NULL; IN_ADDR inaddr; int i; HOSTENT *host = NULL; ipopt = (IpOptionHeader *)(buf + 20); TRACE("Ping 结果: \r\n"); // m_dlg->SetDlgItemText(IDC_EDIT2,m_dlg->m_result); for(i = 0; i < (ipopt->ptr / 4) - 1; i++) { inaddr.S_un.S_addr = ipopt->addr[i]; if (i != 0) { // m_dlg->SetDlgItemText(IDC_EDIT2,m_dlg->m_result); } host = gethostbyaddr((char *)&inaddr.S_un.S_addr, sizeof(inaddr.S_un.S_addr), AF_INET); CString temp; if (host) { temp.Format("(%-15s) %s \r\n", inet_ntoa(inaddr), host->h_name); // m_dlg->m_result+=temp; // m_dlg->SetDlgItemText(IDC_EDIT2,m_dlg->m_result); } else { temp.Format("(%-15s)\r\n", inet_ntoa(inaddr)); // m_dlg->m_result+=temp; // m_dlg->SetDlgItemText(IDC_EDIT2,m_dlg->m_result); } } return; } void CPing::Cleanup() {//清除ICMP包 if (m_hSocket != INVALID_SOCKET) closesocket(m_hSocket); HeapFree(GetProcessHeap(), 0, recvbuf); HeapFree(GetProcessHeap(), 0, icmp_data); // WSACleanup(); return ; } void CPing::ping() {//使用多线程的ping函数 // g_threadContral=false; param = new _PINGTHREADPARAM(this); param->addr_begin=m_addrBegin; param->addr_end=m_addrEnd; AfxBeginThread(PingThreadProc,param); } BOOL CPing::runPing(unsigned int addr) { CString result; m_hSocket = WSASocket (AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0,WSA_FLAG_OVERLAPPED); //创建Socket if (m_hSocket == INVALID_SOCKET) { ((CEdit *)m_pView->GetDlgItem(1020))->SetWindowText("创建Socket失败\n"); return false; } //设置接收超时选项 int bread = setsockopt(m_hSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&m_timeout, sizeof(m_timeout)); if(bread == SOCKET_ERROR) { ((CEdit *)m_pView->GetDlgItem(1020))->SetWindowText("设置socket接收超时选项错误!"); return false; } //设置发送超时选项 bread = setsockopt(m_hSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&m_timeout, sizeof(m_timeout)); if (bread == SOCKET_ERROR) { ((CEdit *)m_pView->GetDlgItem(1020))->SetWindowText("设置socket发送超时选项错误!"); return false; } //转换地址的格式 memset(&m_addrDest, 0, sizeof(m_addrDest)); m_addrDest.sin_family = AF_INET; unsigned char *a; a=(unsigned char*)&addr; m_addrDest.sin_addr.S_un.S_un_b.s_b1=a[3]; m_addrDest.sin_addr.S_un.S_un_b.s_b2=a[2]; m_addrDest.sin_addr.S_un.S_un_b.s_b3=a[1]; m_addrDest.sin_addr.S_un.S_un_b.s_b4=a[0]; result.Format("%s",inet_ntoa(m_addrDest.sin_addr)); result="正在ping "+result+" "; ((CEdit *)m_pView->GetDlgItem(1020))->SetWindowText(result);//inet_ntoa(m_addrDest.sin_addr)); TRACE("m_addrDest.sin_addr = %s\n", inet_ntoa(m_addrDest.sin_addr)); // 创建ICMP包 datasize += sizeof(IcmpHeader); icmp_data =(char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,MAX_PACKET); recvbuf =(char*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,MAX_PACKET); if (!icmp_data) { TRACE(result+"堆分配错误!"); return false; } memset(icmp_data,0,MAX_PACKET); //向ICMP包中填充数据 FillICMPData(icmp_data,datasize); //发送/接收ICMP包的循环,共进行m_pingNumber遍 int nCount=0; while(1) { int bwrote; TRACE("%d\n",nCount); if (nCount++ == m_pingNumber) break; //发送ICMP包 ((IcmpHeader*)icmp_data)->i_cksum = 0; ((IcmpHeader*)icmp_data)->timestamp = GetTickCount(); ((IcmpHeader*)icmp_data)->i_seq = seq_no++; ((IcmpHeader*)icmp_data)->i_cksum =checksum((USHORT*)icmp_data, datasize); bwrote = sendto(m_hSocket, icmp_data, datasize, 0, (struct sockaddr*)&m_addrDest, sizeof(m_addrDest)); if (bwrote == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { TRACE(result+"发送数据超时! "); continue; } TRACE(result+"发送数据函数调用错误!"); return false; } //接收ICMP包 int fromlen = sizeof(m_addrFrom); bread = recvfrom(m_hSocket,recvbuf, MAX_PACKET, 0, (struct sockaddr*)&m_addrFrom, &fromlen); if (bread == SOCKET_ERROR) { if (WSAGetLastError() == WSAETIMEDOUT) { TRACE(result+"接收数据超时!"); continue; } TRACE(result+"接收数据函数调用错误!"); return 0; } //解析ICMP头,显示ping结果 if(DecodeICMPHeader(recvbuf, bread, &m_addrFrom)) { TRACE("\n正确解析ICMP头!!!\n"); return true; } else TRACE(result+"解析ICMP头出错"); }//end while(1) return false; } bool CPing::DecodeICMPHeader(char *buf, int bytes, SOCKADDR_IN* from) {//解析ICMP包头结构信息 IpHeader *iphdr = NULL; IcmpHeader *icmphdr = NULL; unsigned short iphdrlen; DWORD tick; static int icmpcount = 0; iphdr = (IpHeader *)buf; // Number of 32-bit words * 4 = bytes iphdrlen = iphdr->h_len * 4; //得到以毫秒为单位的当前时间 tick = GetTickCount(); //第一次解析ICMP头信息时需要解析IP头选项 if ((iphdrlen == MAX_IP_HDR_SIZE) && (!icmpcount)) DecodeIPOptions(buf, bytes);//解析IP包头可选项信息 CString temp; if (bytes < iphdrlen + ICMP_MIN) { temp.Format("Too few bytes from %s \r\n",inet_ntoa(from->sin_addr)); //m_dlg->m_result+=temp; //m_dlg->SetDlgItemText(IDC_EDIT2,m_dlg->m_result); } icmphdr = (IcmpHeader*)(buf + iphdrlen); if (icmphdr->i_type != ICMP_ECHOREPLY) { temp.Format("nonecho type %d recvd \r\n", icmphdr->i_type); //m_dlg->m_result+=temp; //m_dlg->SetDlgItemText(IDC_EDIT2,m_dlg->m_result); return false; } // 确保当前的ICMP回应是所发送的ICMP包的回应,有可能其它程序也发送了ICMP包 if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) { temp.Format("someone else's packet! \r\n"); return false; } //设置Ping结果信息 /* temp.Format("%d bytes from %s: \r\n", bytes, inet_ntoa(from->sin_addr)); m_dlg->m_result+=temp; temp.Format(" icmp_seq = %d. \r\n", icmphdr->i_seq); m_dlg->m_result+=temp; temp.Format(" time: %d ms \r\n", tick - icmphdr->timestamp); m_dlg->m_result+=temp; temp.Format("校验和 = %d \r\n",icmphdr->i_cksum); m_dlg->m_result+=temp; temp.Format("标识符 = %d \r\n",icmphdr->i_id); m_dlg->m_result+=temp; */ //将IP信息加入list中 _hostInfo hi; hi.destIP=from->sin_addr.S_un.S_addr; hi.time=tick - icmphdr->timestamp; m_pView->m_listHost.AddTail(hi); //将这条信息写入ListContral int iPos=m_pView->m_ctrlList.GetItemCount(); char buffer[10]; _itoa(hi.time,buffer,10); LV_ITEM lvitem1; lvitem1.mask=LVIF_TEXT; lvitem1.iItem=iPos; lvitem1.iSubItem=0; lvitem1.pszText=inet_ntoa(m_addrDest.sin_addr); iPos=m_pView->m_ctrlList.InsertItem(&lvitem1);//返回表项插入后的索引号 lvitem1.iItem=iPos; lvitem1.iSubItem=1; lvitem1.pszText=buffer; m_pView->m_ctrlList.SetItem(&lvitem1); icmpcount++; return true; } USHORT CPing::checksum(USHORT *buffer, int size) {//校验数据 unsigned long cksum=0; while (size > 1) { cksum += *buffer++; size -= sizeof(USHORT); } if (size) { cksum += *(UCHAR*)buffer; } cksum = (cksum >> 16) + (cksum & 0xffff); cksum += (cksum >>16); return (USHORT)(~cksum); } void CPing::FillICMPData(char *icmp_data, int datasize) {//填充ICMP数据 IcmpHeader *icmp_hdr = NULL; char *datapart = NULL; icmp_hdr = (IcmpHeader*)icmp_data; icmp_hdr->i_type = ICMP_ECHO; // 请求一个ICMP回显 icmp_hdr->i_code = 0; icmp_hdr->i_id = (USHORT)GetCurrentProcessId(); icmp_hdr->i_cksum = 0; icmp_hdr->i_seq = 0; datapart = icmp_data + sizeof(IcmpHeader); } UINT PingThreadProc(LPVOID pParam) { _PINGTHREADPARAM* param=(_PINGTHREADPARAM*)pParam; ASSERT(param); CPing *pPing=param->pPing; unsigned int ip; for(ip=param->addr_begin;ip<=param->addr_end;ip++) { if(g_threadContral) { global_criticalsection.Lock(); if(pPing->runPing(ip)==false) continue; pPing->Cleanup(); global_criticalsection.Unlock(); }else break; } ((CEdit *)pPing->m_pView->GetDlgItem(1020))->SetWindowText("ping 结束"); ((CEdit *)pPing->m_pView->GetDlgItem(1017))->SetWindowText("开始ping"); g_threadContral=false; return 0; }