基于VC实现的网络监听功能程序实例
本文所述VC++网络监听器代码,可以实现监听网络连接所使用的协议、源IP地址、目标IP地址等信息的功能,并且能把数据内容绑定到网格控件中显示。具体功能代码部分如下所示:
//线程函数 UINTThreadFun(LPVOIDpParam) { CSniffAppDlg*pDlg=static_cast<CSniffAppDlg*>(pParam); MSGmsg; charbuffer[1000],sourceip[32],*tempbuf; char*ptemp; BYTE*pData=NULL;//实际数据报中的数据 UINTsourceport; CStringstr; HEADIP*pHeadIP; HEADICMP*pHeadICMP; HEADUDP*pHeadUDP; HEADTCP*pHeadTCP; in_addraddr; intret; while(TRUE) { pData=NULL; if(PeekMessage(&msg,pDlg->m_hWnd,WM_CLOSE,WM_CLOSE,PM_NOREMOVE)) { closesocket(pDlg->m_Sock); break; } memset(buffer,0,1000); ret=recv(pDlg->m_Sock,buffer,1000,0); if(ret==SOCKET_ERROR) { continue; } else//接收到数据 { tempbuf=buffer; pHeadIP=(HEADIP*)tempbuf; //获取数据报总长度 WORDlen=ntohs(pHeadIP->totallen); //获取源IP pDlg->m_List.InsertItem(pDlg->m_List.GetItemCount(),""); addr.S_un.S_addr=pHeadIP->sourceIP; ptemp=inet_ntoa(addr); pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,1,ptemp); //获取目的IP addr.S_un.S_addr=pHeadIP->destIP; ptemp=inet_ntoa(addr); pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,2,ptemp); //获取协议名称 ptemp=get_protoname(pHeadIP->proto); strcpy(sourceip,ptemp); pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,0,sourceip); //获取IP数据报总长度 WORDipSumLen=ntohs(pHeadIP->totallen); //IP数据报头总长度 intipHeadLen=20; //获得去除IP层数据的长度 WORDnetlen=ipSumLen-ipHeadLen; //根据不同大协议获得不同协议的数据 switch(pHeadIP->proto) { caseIPPROTO_ICMP: { pHeadICMP=(HEADICMP*)(tempbuf+20); pData=(BYTE*)(pHeadICMP)+4;//ICMP数据报头共4个字节 //获取数据的长度 netlen-=4; break; } caseIPPROTO_UDP: { pHeadUDP=(HEADUDP*)(tempbuf+20); pData=(BYTE*)pHeadUDP+8;//UDP数据报头共8个字节 sourceport=ntohs(pHeadUDP->SourcePort); str.Format("%d",sourceport); //设置源端口 pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,3,str); str.Empty(); netlen-=8; break; } caseIPPROTO_TCP: { pHeadTCP=(HEADTCP*)(tempbuf+20); sourceport=ntohs(pHeadTCP->SourcePort); pData=(BYTE*)pHeadTCP+20;//TCP数据报头共20个字节 str.Format("%d",sourceport); //设置源端口 pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,3,str); str.Empty(); netlen-=20; break; } } //设置数据大小 str.Format("%d",netlen); pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,4,str); str.Empty(); //设置数据 if(pData!=NULL) { str.Format("%s",pData); pDlg->m_List.SetItemText(pDlg->m_List.GetItemCount()-1,5,str); } str.Empty(); } } return0; } voidCSniffAppDlg::OnBeginlisten() { //创建套接字 m_Sock=socket(AF_INET,SOCK_RAW,IPPROTO_IP); charname[128]; memset(name,0,128); hostent*phostent; phostent=gethostbyname(name); DWORDip; ip=inet_addr(inet_ntoa(*(in_addr*)phostent->h_addr_list[0])); inttimeout=4000;//超时4秒 //设置接收数据的超时时间 setsockopt(m_Sock,SOL_SOCKET,SO_RCVTIMEO,(constchar*)&timeout,sizeof(timeout)); sockaddr_inskaddr; skaddr.sin_family=AF_INET; skaddr.sin_port=htons(700); skaddr.sin_addr.S_un.S_addr=ip; //绑定地址 if(bind(m_Sock,(sockaddr*)&skaddr,sizeof(skaddr))==SOCKET_ERROR) { MessageBox("地址绑定错误"); return; } DWORDinBuffer=1; DWORDoutBuffer[10]; DWORDreValue=0; if(WSAIoctl(m_Sock,SIO_RCVALL,&inBuffer,sizeof(inBuffer),&outBuffer,sizeof(outBuffer),&reValue,NULL,NULL)==SOCKET_ERROR) { MessageBox("设置缓冲区错误."); closesocket(m_Sock); return; } else m_pThread=AfxBeginThread(ThreadFun,(void*)this); } voidCSniffAppDlg::OnCancel() { if(m_pThread) { //m_pThread->ExitInstance(); deletem_pThread; } closesocket(m_Sock); CDialog::OnCancel(); }
该实例只是功能部分主要代码,读者可根据自身项目需求进行测试,加以改进与完善之后整合进自身项目中去。