基于VC6.0的抓取TCP/IP数据包的C++实现

#include <winsock2.h>
#include <windows.h>
#include <mstcpip.h>

#pragma comment(lib,"Ws2_32.lib")

#include <iostream>
using namespace std;

//IP首部
typedef struct tIPPackHead
{
      enum PROTOCOL_TYPE{
          PROTOCOL_TCP = 6,
          PROTOCOL_UDP = 17,
          PROTOCOL_ICMP = 1,
          PROTOCOL_IGMP = 2    
      };
      inline unsigned HeadLen() const
      {
          //首部长度单位为4bytes。因此乘4
          return (ver_hlen & 0x0F) << 2;
      }
      inline unsigned PackLen() const
      {
          return wPacketLen;
      }
      BYTE ver_hlen;      //IP协议版本和IP首部长度。高4位为版本,低4位为首部的长度(单位为4bytes)
      BYTE byTOS;       //服务类型
      WORD wPacketLen; //IP包总长度。包括首部,单位为byte。[Big endian]
      WORD wSequence;    //序号,一般每个IP包的序号递增。[Big endian]
      WORD wMarkFragPoi;  
      BYTE byTTL;         //生存时间  
      BYTE byProtocolType; //协议类型,见PROTOCOL_TYPE定义
      WORD wHeadCheckSum;    //IP首部校验和[Big endian]
      DWORD dwIPSrc;         //源地址
      DWORD dwIPDes;         //目的地址
} IP_PK_HEAD;


int DecodeIP(char *buf, int len);

int DecodeIP(char *buf, int len)
{
      int n = len;

      if( n >= sizeof(IP_PK_HEAD) )
      {
          IP_PK_HEAD iphead;
          memcpy( &iphead, buf, sizeof(iphead) );

          //以下三个为Big Endian字节顺序,转换成主机字节顺序
          iphead.wPacketLen = ntohs( iphead.wPacketLen );
          iphead.wSequence = ntohs( iphead.wSequence );
          iphead.wHeadCheckSum = ntohs( iphead.wHeadCheckSum );

          in_addr src,dst;
          src.S_un.S_addr = iphead.dwIPSrc;
          dst.S_un.S_addr = iphead.dwIPDes;

          char strsrc[20],strdst[20];
          strcpy(strsrc, inet_ntoa(src));
          strcpy( strdst , inet_ntoa(dst));

          printf( "IP数据包: ver=%d,hlen=%d,protocol=%d,pklen=%d,seq=%d,src=%s,dst=%s _fcksavedurl=%s,dst=%s",
              iphead.ver_hlen >> 4,
              (iphead.ver_hlen & 0x0F) << 2,
              iphead.byProtocolType,
              iphead.wPacketLen,
              iphead.wSequence,
              strsrc,
              strdst );
      }

      return 0;
}

void AutoWSACleanup()
{
      ::WSACleanup();
}

int main()
{
      //初始化winsock库,使用2.2版本
      u_short wVersionRequested = 0x0202;
      WSADATA wsaData;
      if( SOCKET_ERROR == WSAStartup( wVersionRequested, &wsaData ) )
      {        
          cout << WSAGetLastError();
          return 0;
      }
      atexit( AutoWSACleanup );

      //创建SOCKET
      SOCKET h = socket( AF_INET, SOCK_RAW, IPPROTO_IP);
      if( h == INVALID_SOCKET )
      {
          cout << WSAGetLastError();
          return 0;
      }

      //获取本机地址
      char FAR name[128];  
      if( -1 == gethostname(name, sizeof(name)) )
      {
          closesocket( h );
          cout << WSAGetLastError();
          return 0;
      }

      struct hostent FAR * pHostent;
      pHostent = gethostbyname(name);

      //绑定本地地址到SOCKET句柄
      sockaddr_in addr;
      addr.sin_family = AF_INET;
      addr.sin_addr = *(in_addr*)pHostent->h_addr; //IP
      addr.sin_port = 0; //端口,IP层端口可随意填
      if( SOCKET_ERROR == bind( h,(sockaddr *)&addr,sizeof(addr) ) )
      {
          closesocket( h );
          cout << WSAGetLastError();
          return 0;
      }

      //设置该SOCKET为接收所有流经绑定的IP的网卡的所有数据,包括接收和发送的数据包
      //该函数在mstcpip.h里面,详见MSDN帮助
      u_long sioarg = 1;
      DWORD wt=0;
      if( SOCKET_ERROR == WSAIoctl( h, SIO_RCVALL , &sioarg,sizeof(sioarg),NULL,0,&wt,NULL,NULL ) )
      {
          closesocket( h );
          cout << WSAGetLastError();
          return 0;
      }

      //我们只需要接收数据,因此设置为阻塞IO,使用最简单的IO模型
      u_long bioarg =    0;
      if( SOCKET_ERROR == ioctlsocket( h, FIONBIO , &bioarg ) )
      {
          closesocket( h );
          cout << WSAGetLastError();
          return 0;
      }

      //开始接收数据
      //因为前面已经设置为阻塞IO,recv在接收到数据前不会返回。
      //当返回<=0时表示接收失败,退出循环
      //可以在另一个线程执行此循环,主线程closesocket可以使recv失败而结束循环
      char buf[102400];
      int len = 0;
      do
      {
          len = recv( h, buf, sizeof(buf),0);
          if( len > 0 )
          {
              DecodeIP( buf, len );
          }
      }while( len > 0 );

      closesocket( h );

      return 0;
}
汉化版的vc貌似都没有mstcpip.h文件

内容如下,将内容保存为MSTCPIP.H

然后放到Microsoft Visual Studio\VC98\Include这个文件夹下面即可

// Copyright (C) Microsoft Corporation, 1996-1999
#if _MSC_VER > 1000
#pragma once
#endif

/* Argument structure for SIO_KEEPALIVE_VALS */

struct tcp_keepalive {
    u_long onoff;
    u_long keepalivetime;
    u_long keepaliveinterval;
};

// New WSAIoctl Options

#define SIO_RCVALL            _WSAIOW(IOC_VENDOR,1)
#define SIO_RCVALL_MCAST      _WSAIOW(IOC_VENDOR,2)
#define SIO_RCVALL_IGMPMCAST _WSAIOW(IOC_VENDOR,3)
#define SIO_KEEPALIVE_VALS    _WSAIOW(IOC_VENDOR,4)
#define SIO_ABSORB_RTRALERT   _WSAIOW(IOC_VENDOR,5)
#define SIO_UCAST_IF          _WSAIOW(IOC_VENDOR,6)
#define SIO_LIMIT_BROADCASTS _WSAIOW(IOC_VENDOR,7)
#define SIO_INDEX_BIND        _WSAIOW(IOC_VENDOR,8)
#define SIO_INDEX_MCASTIF     _WSAIOW(IOC_VENDOR,9)
#define SIO_INDEX_ADD_MCAST   _WSAIOW(IOC_VENDOR,10)
#define SIO_INDEX_DEL_MCAST   _WSAIOW(IOC_VENDOR,11)


  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值