基于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();
}
该实例只是功能部分主要代码,读者可根据自身项目需求进行测试,加以改进与完善之后整合进自身项目中去。