MFC下介绍Sniff网络嗅探器代码

typedef struct _IPHEADER    //IP头结构
{
 unsigned char header_len:4;   //IP头大小,4个字节存放
 unsigned char version:4;     //IP版本,4个字节存放
 unsigned char tos;          //服务类型
 unsigned short total_len;    //数据报大小
 unsigned short ident;         //数字报标识
  unsigned short flags;    //一种标志
   unsigned char ttl;  
 unsigned char proto;            //协议
  unsigned short charSum;    //IP数据包检验
   unsigned int sourceIP;     //源ip
    unsigned int destIP;   //目的ip

}IPHEADER;

 

 struct TCPPacketHead        //传输控制协议头结构
{
 WORD SourPort ;           //源端口
 WORD DestPort;            //目的端口
 WORD SeqNo;              //序列号
 DWORD AckNo;              
 BYTE HLen ;               //头大小
 BYTE Flag;                //标志
 WORD WndSize;            
 WORD ChkSum;               //校验位
 WORD UrgPtr;             
};

struct UDPPacketHead           //数据包包头结构
{
 WORD SourPort;            //源端口
     WORD DestPort;            //目的端口
  WORD Len;                //头大小
       WORD ChkSum;               //校验位
};

struct TCMPPacketHead  //ICMP网际控制报文协议
{
  BYTE Type;     //协议类型
  BYTE Code;
  WORD ChkSum;    //校验
};

 

int iRet = 0;
char buf[1000];
char* bufwork;
IPHEADER* pIpHeader;
in_addr ina;
char szSource[16], szDest[16], szErr[50];
char* pSource, *pDest;
char* pLastBuf = NULL;
WORD sourport, destport;
int HdrLen, totallen;
struct TCPPacketHead * pTCPHead;
struct TCMPPacketHead* pICMPHead;
struct UDPPacketHead* pUDPHead;
BYTE* pData = NULL;

 

while(true)     //死循环
{
 //检测消息队列中的WM_CLOSE消息 
 memset(buf, 0, sizeof(buf));    //初始化字符数组
 //接收数据
   iRet = recv(pDlg->m_socket, buf, sizeof(buf), 0);
   if(*buf)
   { 
       bufwork = buf;    //字符串赋值   
    pIpHeader = (IPHEADER*)bufwork;        //获取ip包的头
    WORD iLen= ntohs(pIpHeader->total_len);   //获得数据包大小
    while(true)   //嵌套死循环分析数据
    {  
     if(iLen < iRet)      //如果数据报大小小于接收到的数据大小
     {
      ina.S_un.S_addr = pIpHeader->sourceIP;     //获取源ip
      pSource = inet_ntoa(ina);             //将网络ip转化为主机上的源ip地址
      strcpy(szSource, pSource);
      ina.S_un.S_addr = pIpHeader->destIP;     //获取目标ip
      pDest = inet_ntoa(ina);             //将网络ip转化为主机上的目标ip地址    
      strcpy(szDest, pDest);    
      CString str, strProto, strSourPort, strDestPort, strData, strSize;
      //得到数据报的协议名称
      // strProto = get_proto_name(pIpHeader->proto);
      HdrLen = pIpHeader->header_len&0xf;     //获得IP头大小
      HdrLen *= 4;
      totallen = ntohs(pIpHeader->total_len);         //获得数据报大小,转化为主机     
      totallen -= HdrLen;        //数据包大小除去IP头大小
      //对不同协议的头部数据进行分析          
      switch(pIpHeader->proto)
      {
      case IPPROTO_ICMP:    //网际控制报文协议
       {
        pICMPHead = (struct TCMPPacketHead*)(buf+HdrLen);   //获取除去IP头的ICMP报文
        strSourPort = "-";
        strDestPort = "-";
        pData = ((BYTE*)pICMPHead) + ICMP_HEAD_LEN;     //保存出去ICMP头的字节内容             
        totallen -= ICMP_HEAD_LEN;        //总大小出去IP头和ICMP头后
        break;
       }
      case IPPROTO_TCP:      //传输控制协议
       {
                       
            pTCPHead = (struct TCPPacketHead *)(buf+HdrLen);   //获取除去IP头的TCP报文
                         sourport = ntohs(pTCPHead->SourPort);      //得到源端口和目的端口号
       destport = ntohs(pTCPHead->DestPort);
       strSourPort.Format("%d",sourport );
                        strDestPort.Format("%d",destport); 
                  
      HdrLen = (pTCPHead->HLen)>>4;
                       HdrLen *= 4;
                        pData = ((BYTE*)pTCPHead) +HdrLen;               //  //保存出去TCP头的字节内容
                         totallen -= HdrLen;                    //总大小出去IP头和TCP头后
       break;
       }
      case IPPROTO_UDP:
       {
           pUDPHead = (struct UDPPacketHead*)(buf+HdrLen);   //获取除去IP头的UDP报文
             sourport = ntohs(pUDPHead->SourPort);      //得到源端口和目的端口号
       destport = ntohs(pUDPHead->DestPort);
       strSourPort.Format("%d",sourport );
                        strDestPort.Format("%d",destport); 
             pData = ((BYTE*)pTCPHead) +UDP_HEAD_LEN;               //  //保存除去UDP头的字节内容
         totallen -= UDP_HEAD_LEN;                    //总大小出去IP头和UDP头后
                        break;
       }
      }
             //  CString strSize, strData;
              strSize.Format("%d",totallen );
      strData.Format("%s", pData);
      pDlg->AddData("", szSource, strSourPort, szDest, strDestPort,strSize,  strData);
      if(iLen < iRet)            //保证获取完整的ip包
      {
                  iRet -= iLen;                  
                   bufwork +=  iLen;
                  
           pIpHeader = (IPHEADER*)bufwork;        //获取ip包的头
      }
      else
       break;    //如果pIpHeader->total_len == iRet就退出
     }
     else     //如果pIpHeader->total_len ,已经读到buffer的最后部分,就是i包的长度
     {
      int iLast = iLen -iRet;    //剩余的数据
      pLastBuf = new char[iLen];   
      int iReaden = iRet;     //已经达到的数据
      memcpy(pLastBuf, bufwork, iReaden);    //已经到达的数据
               
              iRet = recv(pDlg->m_socket, pLastBuf+iReaden, iLast, 0)  //继续接收剩余的数据,并存入之前的总接收包中,从iReaden处开始

        bufwork = pLastBuf;    //记录总的接收数据
                 pIpHeader = (IPHEADER*)bufwork;        //改变获取ip包的头
     if(iRet !=iLast )                    //如果还是没有接收完剩余数据.,就读
     {
                      iReaden+=iRet;        //已经到达的数据
                     iLast -= iRet;         // 剩余的数据

      while(true)
      {
        //继续接收剩余的数据,并存入之前的总接收包中,从iReaden处开始
                           iRet =   iRet = recv(pDlg->m_socket, pLastBuf+iReaden, iLast, 0) ;
                            iReaden+=iRet;        //已经到达的数据
                                iLast -= iRet;         // 剩余的数据
        if(iLast <= 0)
        {
         break;
        }

 

 

你可能感兴趣的:(MFC下介绍Sniff网络嗅探器代码)