精华内容
下载资源
问答
  • 解析IP数据包

    2017-02-17 14:35:28
    计算机网络 C语言 解析IP数据包
  • 基于C++和winpcap编写的网络程序,实现监听并解析IP数据包! 运行程序,按提示输入要选择的网卡序列,再次输入需要不活的IP数据包的个数,然后程序自动运行捕获。 捕获后开始解析,从数据链路层开始解析...
  • 解析IP数据包.cpp

    2019-05-23 18:30:42
    并根据TCP/IP协议解析IP数据包; Winpcap由内核级的数据包过滤器,底层动态链接库(packet.dll)和一个高层的独立于系统的库(wpcap.dll)组成。 PS:为什么不能设置免费/1币分享,促进萌新们交流学习啊。。。
  • (1)捕获网络中的IP数据包解析数据包的内容,并将结果显示出来。 (2) 显示内容包括:捕获的IP包的版本、源地址、目的地址、源端口、目的端口、协议类型、IP包总长度、IP包头总长度、IP数据包长度等内容。 (3) 设置...
  • 点击exe文件可以直接在命令行窗口下运行,支持手动输入时间,输出IP包的信息
  • 计算机网络的解析ip数据包课程设计,亲测运行成功。问题一般出在头文件的引用上
  • 本次设计的目标是捕获网络中的IP数据包解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件。 实验要求: 1)以命令行形式运行:ipparse logfile , 其中ipparse是程序名,而logfile则代表记录结果的...
  • IP数据包解析

    2019-01-04 17:06:23
    ip数据包解析,分为服务端与客户端,客户端发送消息,服务端解析,并打印输出
  • C++解析IP数据包程序

    2017-06-20 09:18:46
    点击exe文件可以直接在命令行窗口下运行,支持手动输入时间,输出IP包的信息
  • C++ 捕获与解析IP数据包 (winpcap)

    万次阅读 多人点赞 2018-12-28 11:21:48
    捕获后开始解析,从数据链路层开始解析, 1) 如果网络层协议是IP协议,则开始解析网络层IP数据包。 2) 如果运输层协议是TCP协议则解析运输层TCP数据包。 3) 如果网络层协议是APP协议,则不在进一步解析网络...

    源代码链接:https://download.csdn.net/download/chd_lcj/10891420

    (不知道为什么积分涨到4积分了。。。原先只是单纯的想分享下的,结果最低只能设置1积分)

    //网络编程学习经验记录贴

     ***选择正在联网的网卡,如果你不知道就一个个试!***

    ***关闭防火墙/关闭防火墙/关闭防火墙***

    winpcap简介

    WinPcap 是由伯克利分组捕获库派生而来的分组捕获库,它是在Windows 操作平台上来实现对底层包的截取过滤。

    WinPcap 为用户级的数据包提供了Windows 下的一个平台。

    WinPcap 是 BPF 模型和 Libpcap 函数库在 Windows 平台下网络数据包捕获和网络状态分析的一种体系结构,这个体系结构是由一个核心的包过滤驱动程序,一个底层的动态连接库 Packet.dll 和一个高层的独立于系统的函数库 Libpcap 组成。底层的包捕获驱动程序实际为一个协议网络驱动程序,通过对 NDIS 中函数的调用为 Win95、Win98、WinNT、和 Win2000 提供一类似于 UNIX 系统下 Berkeley Packet Filter 的捕获和发送原始数据包的能力。Packet.dll 是对这个 BPF 驱动程序进行访问的 API 接口,同时它有一套符合 Libpcap 接口(UNIX 下的捕获函数库)的函数库。WinPcap的结构图如图1。

    WinPcap 包括三个部分:

    第一个模块NPF(Netgroup Packet Filter),是一个虚拟设备驱动程序文件。它的功能是过滤数据包,并把这些数据包原封不动地传给用户态模块,这个过程中包括了一些操作系统特有的代码。

    第二个模块packet.dll为win32平台提供了一个公共的接口。不同版本的Windows系统都有自己的内核模块和用户层模块。Packet.dll用于解决这些不同。调用Packet.dll的程序可以运行在不同版本的Windows平台上,而无需重新编译。

    第三个模块 Wpcap.dll是不依赖于操作系统的。它提供了更加高层、抽象的函数。

    packet.dll和Wpcap.dll:packet.dll直接映射了内核的调用。 Wpcap.dll提供了更加友好、功能更加强大的函数调用。WinPcap的优势提供了一套标准的抓包接口,与libpcap兼容,可使得原来许多UNIX平台下的网络分析工具快速移植过来便于开发各种网络分析工具,充分考虑了各种性能和效率的优化,包括对于NPF内核层次上的过滤器支持,支持内核态的统计模式,提供了发送数据包的能力。

    利用winpcap进行网络数据包的捕获和过滤的设计步骤
    1)打开网卡,并设为混杂模式。
    
    2)回调函数 Network Tap 在得到监听命令后,从网络设备驱动程序处收集数据包把监听到的数据包负责传送给过滤程序。
    
    3)当 Packet filter 监听到有数据包到达时,NDIS 中间驱动程序首先调用分组驱动程序,该程序将数据传递给每一个参与进程的分组过滤程序。
    
    4)然后由 Packet filter 过滤程序决定哪些数据包应该丢弃,哪些数据包应该接收,是否需要将接收到的数据拷贝到相应的应用程序。
    
    5)通过分组过滤器后,将数据未过滤掉的数据包提交给核心缓冲区。然后等待系统缓冲区满后,再将数据包拷贝到用户缓冲区。监听程序可以直接从用户缓冲区中读取捕获的数据包。
    
    6)关闭网卡。

    网络数据包捕获的原理

    以太网(Ethernet)具有共享介质的特征,信息是以明文的形式在网络上传输,当网络适配器设置为监听模式(混杂模式,Promiscuous)时,由于采用以太网广播信道争用的方式,使得监听系统与正常通信的网络能够并联连接,并可以捕获任何一个在同一冲突域上传输的数据包。IEEE802.3 标准的以太网采用的是持续 CSMA 的方式,正是由于以太网采用这种广播信道争用的方式,使得各个站点可以获得其他站点发送的数据。运用这一原理使信息捕获系统能够拦截的我们所要的信息,这是捕获数据包的物理基础。
    以太网是一种总线型的网络,从逻辑上来看是由一条总线和多个连接在总线上的站点所组成各个站点采用上面提到的 CSMA/CD 协议进行信道的争用和共享。每个站点(这里特指计算机通过的接口卡)网卡来实现这种功能。网卡主要的工作是完成对于总线当前状态的探测,确定是否进行数据的传送,判断每个物理数据帧目的地是否为本站地址,如果不匹配,则说明不是发送到本站的而将它丢弃。如果是的话,接收该数据帧,进行物理数据帧的 CRC 校验,然后将数据帧提交给LLC 子层。

    网卡具有如下的几种工作模式:
    1)   广播模式(Broad Cast Model):它的物理地址(MAC)地址是 0Xffffff 的帧为广播帧,工作在广播模式的网卡接收广播帧。
    2)多播传送(MultiCast Model):多播传送地址作为目的物理地址的帧可以被组内的其它主机同时接收,而组外主机却接收不到。但是,如果将网卡设置为多播传送模式,它可以接收所有的多播传送帧,而不论它是不是组内成员。
    3)直接模式(Direct Model):工作在直接模式下的网卡只接收目地址是自己 Mac地址的帧。
    4)混杂模式(Promiscuous Model):工作在混杂模式下的网卡接收所有的流过网卡的帧,信包捕获程序就是在这种模式下运行的。
    网卡的缺省工作模式包含广播模式和直接模式,即它只接收广播帧和发给自己的帧。如果采用混杂模式,一个站点的网卡将接受同一网络内所有站点所发送的数据包这样就可以到达对于网络信息监视捕获的目的。

    IP数据包头字段说明

    1. 版本号(Version):长度4比特。标识目前采用的IP协议的版本号。一般的值为0100(IPv4),0110(IPv6) 
    2. IP包头长度(HeaderLength):长度4比特。这个字段的作用是为了描述IP包头的长度,因为在IP包头中有变长的可选部分。该部分占4个bit位,单位为32bit(4个字节),即本区域值= IP头部长度(单位为bit)/(8*4),因此,一个IP包头的长度最长为“1111”,即15*4=60个字节。IP包头最小长度为20字节。 
    3. 服务类型(Type of Service):长度8比特。8位 按位被如下定义 PPP D T R C 0  但是TOS字段已经作为区分服务(Diffsrv)架构一部分被重新定义了,开始的6位构成区分服务代码点(DiffServ Code Piont,DSCP),利用这6位可以定义64个不同的服务类别。 
    4. ECN显式拥塞通知 
    5. IP包总长(Total Length):长度16比特。 以字节为单位计算的IP包的长度 (包括头部和数据),所以IP包最大长度65535字节。 
    6. 标识符(Identifier)(数据报ID):长度16比特。该字段和Flags和Fragment Offest字段联合使用,对大的上层数据包进行分段(fragment)操作。路由器将一个包拆分后,所有拆分开的小包被标记相同的值,以便目的端设备能够区分哪个包属于被拆分开的包的一部分。 
    7. 标记(Flags):长度3比特。该字段第一位不使用。第二位是DF(Don't Fragment)位,DF位设为1时表明路由器不能对该上层数据包分段。如果一个上层数据包无法在不分段的情况下进行转发,则路由器会丢弃该上层数据包并返回一个错误信息。第三位是MF(More Fragments)位,当路由器对一个上层数据包分段,则路由器会在除了最后一个分段的IP包的包头中将MF位设为1。 
    8. 片偏移(Fragment Offset):长度13比特。表示该IP包在该组分片包中位置,接收端靠此来组装还原IP包。 
    9. 生存时间(TTL):长度8比特。当IP包进行传送时,先会对该字段赋予某个特定的值。当IP包经过每一个沿途的路由器的时候,每个沿途的路由器会将IP包的TTL值减少1。如果TTL减少为0,则该IP包会被丢弃。这个字段可以防止由于路由环路而导致IP包在网络中不停被转发。 
    10. 协议(Protocol):长度8比特。标识了上层所使用的协议。 
    11. 以下是比较常用的协议号: 
      ICMP   IGMP   
      6      TCP  
      17     UDP  
      88     IGRP   
      89     OSPF 

    12. 头部校验(Header Checksum):长度16位。用来做IP头部的正确性检测,但不包含数据部分。 因为每个路由器要改变TTL的值,所以路由器会为每个通过的数据包重新计算这个值。 
    13. 起源和目标地址(Source and Destination Addresses):这两个地段都是32比特。标识了这个IP包的起源和目标地址。要注意除非使用NAT,否则整个传输的过程中,这两个地址不会改变。 
    14. 可选项(Options):这是一个可变长的字段。该字段属于可选项,主要用于测试,由起源设备根据需要改写。可选项目包含以下内容: 
    15. 松散源路由(Loose source routing):给出一连串路由器接口的IP地址。IP包必须沿着这些IP地址传送,但是允许在相继的两个IP地址之间跳过多个路由器。 
    16. 严格源路由(Strict source routing):给出一连串路由器接口的IP地址。IP包必须沿着这些IP地址传送,如果下一跳不在IP地址表中则表示发生错误。 
    17. 路由记录(Record route):当IP包离开每个路由器的时候记录路由器的出站接口的IP地址。 
    18. 时间戳(Timestamps):当IP包离开每个路由器的时候记录时间。 
    19. 填充(Padding):因为IP包头长度(Header Length)部分的单位为32bit,所以IP包头的长度必须为32bit的整数倍。因此,在可选项后面,IP协议会填充若干个0,以达到32bit的整数倍。

    逻辑地址和物理地址:

    (1)逻辑地址:(工作在网络层,网络级)也称为IP地址,具有特征 ① 全局唯一性;② 使用软件来实现网络中地址管理;③ 占32位,4字节;

    (2) 物理地址:也称为硬件地址、链路地址或MAC地址,(工作在网络接口层)具有特征:① 本地范围唯一性;② 使用硬件实现(路由器、计算机有设置MAC地址的位置);③ 占48位,12字节,16进制表示!例如:74-E5-0B-35-60-16 :0111  0100-1110  0101-0000  1011-0011  0101-0110  0000-0001  0110。

    主要案例功能实现:

    运行程序,按提示输入要选择的网卡序列,再次输入需要不活的IP数据包的个数,然后程序自动运行捕获。
    捕获后开始解析,从数据链路层开始解析,
     
    1)	如果网络层协议是IP协议,则开始解析网络层IP数据包。
    2)	如果运输层协议是TCP协议则解析运输层TCP数据包。
    3)	如果网络层协议是APP协议,则不在进一步解析网络层数据包。
    4)	如果运输层协议是UDP协议,则不在进一步解析运输层数据包。
    

    代码如下:

    #include <Winsock2.h>
    #include<iostream>
    #include "pcap.h"
    #include "stdio.h"
    #include<time.h>
    #include <string>
    #include <fstream>  //文件的输入输出;
    #pragma comment(lib,"ws2_32.lib")
    #pragma comment(lib,"wpcap.lib")
    using namespace std;
    
    /*下边是以太网的协议格式 */
    struct ethernet_header
     { 
    	u_int8_t ether_dhost[6];  /*目的以太地址*/
    	u_int8_t ether_shost[6];  /*源以太网地址*/
    	u_int16_t ether_type;      /*以太网类型*/
     };
    
    /*ip地址格式*/
    typedef u_int32_t in_addr_t;
    
    struct ip_header
     {
    #ifdef WORKS_BIGENDIAN
      u_int8_t ip_version:4,    /*version:4*/
           ip_header_length:4; /*IP协议首部长度Header Length*/
    #else
     u_int8_t ip_header_length:4,
           ip_version:4;
    #endif
     u_int8_t ip_tos;         /*服务类型Differentiated Services  Field*/
     u_int16_t ip_length;  /*总长度Total Length*/
     u_int16_t ip_id;         /*标识identification*/
     u_int16_t ip_off;        /*片偏移*/
     u_int8_t ip_ttl;            /*生存时间Time To Live*/
     u_int8_t ip_protocol;        /*协议类型(TCP或者UDP协议)*/
     u_int16_t ip_checksum;  /*首部检验和*/
            struct in_addr  ip_source_address; /*源IP*/
            struct in_addr  ip_destination_address; /*目的IP*/
     };
    
    /*关于tcp头部的定义*/
    struct tcp_header
     { 
      u_int16_t tcp_source_port;		  //源端口号
      
      u_int16_t tcp_destination_port;	//目的端口号
      
      u_int32_t tcp_acknowledgement;	//序号
      
      u_int32_t tcp_ack;	//确认号字段
     #ifdef WORDS_BIGENDIAN
      u_int8_t tcp_offset:4 ,
         tcp_reserved:4;
     #else
      u_int8_t tcp_reserved:4,
         tcp_offset:4;
     #endif
      u_int8_t tcp_flags;
      u_int16_t tcp_windows;	//窗口字段
      u_int16_t tcp_checksum;	//检验和
      u_int16_t tcp_urgent_pointer;	//紧急指针字段
    };
    
    
    
    /*下边实现tcp数据包分析的函数定义tcp_protocol_packet_callback*/
    void tcp_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr*
    packet_header,const u_char* packet_content)
    {
         struct tcp_header *tcp_protocol ;     /*tcp协议变量*/
         u_char flags;                          /*标记*/
         int header_length;                  /*头长度*/
         u_short source_port;           /*源端口*/
         u_short destination_port;   /*目的端口*/
         u_short windows;                /*窗口大小*/
         u_short urgent_pointer;     /*紧急指针*/
         u_int sequence;                 /*序列号*/
         u_int acknowledgement;   /*确认号*/
         u_int16_t   checksum;       /*检验和*/
         tcp_protocol=(struct tcp_header *) (packet_content+14+20);  /*获得tcp首部内容*/
         source_port =ntohs(tcp_protocol->tcp_source_port);                  /*获得源端口号*/
         destination_port =ntohs(tcp_protocol->tcp_destination_port); /*获得目的端口号*/
         header_length =tcp_protocol->tcp_offset *4;                            /*获得首部长度*/
         sequence =ntohl(tcp_protocol->tcp_acknowledgement);        /*获得序列号*/
         acknowledgement =ntohl(tcp_protocol->tcp_ack);
         windows = ntohs(tcp_protocol->tcp_windows);
         urgent_pointer = ntohs(tcp_protocol->tcp_urgent_pointer);
         flags = tcp_protocol->tcp_flags;
         checksum =ntohs (tcp_protocol->tcp_checksum);
         printf("\n==========    运输层(TCP协议)    ==========\n");
         printf("源端口:\t %d\n",source_port);
         printf("目的端口:\t %d\n",destination_port);
    
         int min= ( destination_port <source_port )? destination_port : source_port ;
         cout<<"应用层协议是:\t";
         switch (min)
       {
          case 80:printf(" http 用于万维网(WWW)服务的超文本传输协议(HTTP)");
              break;
      
          case 21:printf(" ftp 文件传输协议(FTP)");
              break;
      
          case 23:printf(" telnet Telnet 服务  ");
              break;
      
          case 25:printf(" smtp 简单邮件传输协议(SMTP)");
              break;
      
          case 110:printf(" pop3 邮局协议版本3 ");
              break;
          case 443:printf(" https 安全超文本传输协议(HTTP) ");
              break;
    
          default :printf("【其他类型】 ");
              break;
           }
     cout<<endl;
     printf("序列号:\t %u \n",sequence);
     printf("确认号:\t%u \n",acknowledgement);
     printf("首部长度:\t%d \n",header_length);
     printf("保留字段:\t%d \n",tcp_protocol->tcp_reserved);
     printf("控制位:");
     if (flags & 0x08)  printf("\t【推送 PSH】");
     if (flags & 0x10)  printf("\t【确认 ACK】 ");
     if (flags & 0x02)  printf("\t【同步 SYN】");
     if (flags & 0x20)  printf("\t【紧急 URG】");
     if (flags & 0x01)  printf("\t【终止 FIN】");
     if (flags & 0x04)  printf("\t【复位 RST】");
    
     printf("\n");
     printf("窗口大小 :\t%d \n",windows);
     printf("检验和 :\t%d\n",checksum);
     printf("紧急指针字段 :\t%d\n",urgent_pointer);
    }
    /*下边实现IP数据包分析的函数定义ethernet_protocol_packet_callback*/
    void ip_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr*
    packet_header,const u_char* packet_content)
     {
      struct ip_header *ip_protocol;   /*ip协议变量*/
      u_int  header_length;    /*长度*/
      u_int  offset;                   /*片偏移*/
      u_char  tos;                     /*服务类型*/
      u_int16_t checksum;    /*首部检验和*/
      ip_protocol=(struct ip_header*) (packet_content+14); /*获得ip数据包的内容去掉以太头部*/
      checksum=ntohs(ip_protocol->ip_checksum);      /*获得校验和*/
      header_length=ip_protocol->ip_header_length*4; /*获得长度*/
      tos=ip_protocol->ip_tos;    /*获得tos*/
      offset=ntohs(ip_protocol->ip_off);   /*获得偏移量*/
         printf("\n##########    网络层(IP协议)    ########### \n");
         printf("IP版本:\t\tIPv%d\n",ip_protocol->ip_version);
         printf("IP协议首部长度:\t%d\n",header_length);
         printf("服务类型:\t%d\n",tos);
         printf("总长度:\t\t%d\n",ntohs(ip_protocol->ip_length));/*获得总长度*/
         printf("标识:\t\t%d\n",ntohs(ip_protocol->ip_id));  /*获得标识*/
         printf("片偏移:\t\t%d\n",(offset&0x1fff)*8);    /**/
         printf("生存时间:\t%d\n",ip_protocol->ip_ttl);     /*获得ttl*/ 
         printf("首部检验和:\t%d\n",checksum);
         printf("源IP:\t%s\n",inet_ntoa(ip_protocol->ip_source_address));          /*获得源ip地址*/
         printf("目的IP:\t%s\n",inet_ntoa(ip_protocol->ip_destination_address));/*获得目的ip地址*/
         printf("协议号:\t%d\n",ip_protocol->ip_protocol);         /*获得协议类型*/
         cout<<"\n传输层协议是:\t";
     switch(ip_protocol->ip_protocol)
     {     
       case 6 :
           printf("TCP\n");
           tcp_protocol_packet_callback(argument,packet_header,packet_content);
           break; /*协议类型是6代表TCP*/
       case 17:
           printf("UDP\n");
           break;/*17代表UDP*/
       case 1:
           printf("ICMP\n");
           break;/*代表ICMP*/
       case 2:
           printf("IGMP\n");
           break;/*代表IGMP*/
      default :break;
     }
     }
    
    void ethernet_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr *packet_header,const u_char* packet_content)
     {
     u_short ethernet_type;                                     /*以太网协议类型*/
     struct ethernet_header *ethernet_protocol;  /*以太网协议变量*/
     u_char *mac_string;
     static int packet_number=1;
     printf("\n*** ****** ******* *********   ********* ******* ****** ***\n");
     printf("\t!!!!!#    第【 %d 】个IP数据包被捕获    #!!!!!\n",packet_number);
     printf("\n==========    链路层(以太网协议)    ==========\n");
     ethernet_protocol =(struct ethernet_header *) packet_content;  /*获得一太网协议数据内容*/
     printf("以太网类型为 :\t");
     ethernet_type=ntohs(ethernet_protocol->ether_type); /*获得以太网类型*/
     printf("%04x\n",ethernet_type);
    
      switch(ethernet_type)            /*判断以太网类型的值*/
          {
            case 0x0800 :  
                printf("网络层是:\tIPv4协议\n");break;
            case 0x0806 :  
                printf("网络层是:\tARP协议\n");break;
            case 0x8035 :  
                printf("网络层是:\tRARP 协议\n");break;
            default: break;
          }
    /*获得Mac源地址*/
    printf("Mac源地址:\t");
    mac_string=ethernet_protocol->ether_shost;
    printf("%02x:%02x:%02x:%02x:%02x:%02x:\n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
    
    /*获得Mac目的地址*/
    printf("Mac目的地址:\t");
    mac_string=ethernet_protocol->ether_dhost;
    printf("%02x:%02x:%02x:%02x:%02x:%02x:\n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
    
     switch (ethernet_type)
    {
        case 0x0800:
            /*如果上层是IPv4ip协议,就调用分析ip协议的函数对ip包进行贩治*/ 
            ip_protocol_packet_callback(argument,packet_header,packet_content);
            break;
        default :break;
     }
      packet_number++;
    }
    main()
    {
         cout<<"==========    解析IP数据包    ==========\n";
         pcap_if_t  *alldevs;
         pcap_if_t *d;
         int inum=0;
         int i=0;
         pcap_t *adhandle;
         char errbuf[PCAP_ERRBUF_SIZE];
    
      /* 获得网卡的列表 */
      if (pcap_findalldevs(&alldevs, errbuf) == -1)
      {
        fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
        exit(1);
      }
     
      /* 打印网卡信息 */
      for(d=alldevs; d; d=d->next)
      {
        printf("%d. %s", ++i, d->name);
        if (d->description)
            printf(" (%s)\n", d->description);
        else
            printf(" (No description available)\n");
      }
     
      if(i==0)
      {
        printf("\n没有发现接口!确保安装了LibPcap.\n");
        return -1;
      }
    
      printf("\n【输入要选择打开的网卡号 (1-%d)】:\t",i);
      scanf("%d", &inum);               //输入要选择打开的网卡号
     
      if(inum < 1 || inum > i) //判断号的合法性
      {
        printf("\n网卡号超出范围.\n");
        /*释放设备列表 */
        pcap_freealldevs(alldevs);
        return -1;
      }
     
      /* 找到要选择的网卡结构 */
      for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);
     
      /* 打开选择的网卡 */
      if ( (adhandle= pcap_open_live(d->name, /* 设备名称*/
                      65536,   /* 最大值.*/
                      /*65536允许整个包在所有mac电脑上被捕获.*/
                      1,       /* 混杂模式*/
    
    /*
    
    混杂模式是指一台主机能够接受所有经过它的数据流,不论这个数据流的目的地址是不是它,它都会接受这个数据包。也就是说,混杂模式下,网卡会把所有的发往它的包全部都接收。在这种情况下,可以接收同一集线器局域网的所有数据。
    
    */
                      1000,     /* 读超时为1秒*/
                      errbuf   /* error buffer*/
                      ) ) == NULL)
      {
        fprintf(stderr,"\n无法打开适配器.\t %s 不被LibPcap支持\n");
        /* Free the device list */
        pcap_freealldevs(alldevs);
        return -1;
      }
    
      printf("\n监听 %s...\n", d->description);
      /* 现在,我们不再需要设备列表, 释放它 */
      pcap_freealldevs(alldevs);
      int cnt = -1;
      cout<<"\n【将要捕获数据包的个数】:\t\t";
      cin>>cnt;
      /* 开始以回调的方式捕获包
      函数名称:int pcap_loop(pcap_t * p,int cnt, pcap_handler callback, uchar * user);
      函数功能:捕获数据包,不会响应pcap_open_live()函数设置的超时时间
      */
      pcap_loop(adhandle,cnt, ethernet_protocol_packet_callback, NULL);
      cout<<"\n\t!!!!!#    解析IP数据包结束    #!!!!!\n";
      return 0;
    }
    

    ***将winpcap的头文件和库记得导入***

     ***选择正在联网的网卡,如果你不知道就一个个试!***

    ***关闭防火墙/关闭防火墙/关闭防火墙***

    1

    tcp

    展开全文
  • 捕获网络中的IP数据包解析数据包的内容,将结果显示在标准输出上。以命令行形式运行:ipparse logfile,其中ipparse是程序名, 而logfile则代表记录结果的日志文件;在标准输出和日志文件中写入捕获的IP包的版本、...
  • 07届的,C++编写,内有结果,详细过程,全新上市,信息学院全体适用!!!
  • 解析ip数据包

    2012-06-13 18:29:21
    解析ip数据包 武汉理工大学 计算机网络
  • 本章课程设计的目的就是设计一个解析IP数据包的程序,并根据这个程序,说明IP数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。 课程设计意义: 1、 有利于编程能力的提高 在做设计的过程...
  • IP数据包解析程序

    2015-10-17 22:05:23
    2)在标准输出和日志文件中写入捕获的IP包的版本、头长度、服务类型、数据包总长度、数据包标识、分段标志、分段偏移值、生存时间、上层协议类型、头校验和、源IP地址和目的IP地址等内容。 3)能够解析不同协议...
  • 计算机网络课程设计解析IP数据包.pdf
  • 数据通信与网络课程设计实践报告解析IP数据包.doc
  • 本资源是个人所做的课程设计,内容是计算机网络方面的解析IP数据包,源码齐全。
  • 设计一个解析IP数据包的程序,并根据这个程序,说明IP数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。 本实验的目标是捕获网络中的IP数据包,解析数据包的内容,见个结果显示在标准输出...
  • 课设题目 1.监控IP包流量     本课程设计的目的是熟悉IP包格式和加深对IP协议的理解。要求编制程序,监控网络,捕获一段时间内网络上的 IP...2.解析IP数据包     课程设...

    课设题目

    1.监控IP包流量
        本课程设计的目的是熟悉IP包格式和加深对IP协议的理解。要求编制程序,监控网络,捕获一段时间内网络上的 IP数据包,按IP数据包的源地址统计出该源地址在该时间段内发出的IP包的个数,将其写入日志文件中或用图形表示出来(建议用图形表示出统计结果)。
    2.解析IP数据包
        课程设计的目的就是设计一个解析IP数据包的程序,并根据这个程序,说明IP数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。本设计的目标是捕获网络中的IP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件)

    成果展示

    1.MFC运行结果
    在这里插入图片描述
    2.日志文件
    在这里插入图片描述

    开发步骤

    1、配置环境
    1)安装底层驱动:在Winpcap官网下载并安装Winpcap.exe
    2)下载 wpdpack开发包

    • 在开发环境(VC)中导入Lib和Include 文件夹路径。VC导入步骤(工具->选项->目录,分别在Include Files和Library Files中加入…/wpdpack/Include和…/wpdpack/Lib)
      在这里插入图片描述
      3)创建MFC工程后,在应用程序中导入需要的DLL和头文件
    • 方法一:VC下:工程->设置->链接 在Object/Library modules下添加ws2_32.lib wpcap.lib(注意中间的空格)
    • 方法二:在源文件中添加命令处理:
      #pragma comment(lib, “ws2_32.lib”)
      #pragma comment(lib, “wpcap.lib”)
      在这里插入图片描述
      2、下载MFC程序,打开dsw文件(网上教程很多,我就直接放完整项目代码了)
      运行即可。
      注意:可能会报错。根据错误提示,百度,就可以解决。
      在这里插入图片描述

    总结

    1. 其实课设海轰选的题目是监控IP数据包,但是做完以后,发现其实监控IP就是统计从源IP地址发出数据包的个数,既然可以统计,那么一定可以解析出每一个IP数据包的内容,所以后面又用了半天时间把解析IP数据包加上了。
    2. 通过这次课设,对MFC又重新回顾了一遍,毕竟去年C++课设用MFC写了一个画图板,对MFC还是有一定的了解的。

    课设相关文件

    • 监控IP数据包详细文档
    • 课设报告
    • 监控IP数据包源代码(简版)
    • 监控、解析IP数据包源代码(二合一版)

    获取资料方法
    微信公众号:海轰Pro
    回复: 海轰

    展开全文
  • 本文件包含解析IP数据包的源程序及报告,是计算机网络课程设计的报告,里面有详细的源程序代码及报告格式及心得体会
  • IP数据包的捕获与分析论文,内有详细代码
  • 网络协议分析的课程设计,题目IP数据包解析,改程序的主要功能是抓取本地主机的IP数据包,并解析
  • 计算机网络课程设计——解析IP和ARP数据包

    千次阅读 多人点赞 2019-12-27 13:58:03
    1)解析IP数据包 课程设计的目的就是设计一个解析IP数据包的程序,并根据这个程序,说明IP数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。本设计的目标是捕获网络中的IP数据包,解析...

    1.课程设计要求:

    1)解析IP数据包

    课程设计的目的就是设计一个解析IP数据包的程序,并根据这个程序,说明IP数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。本设计的目标是捕获网络中的IP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件。

    2)解析ARP数据包

    课程设计的目的是对网络上的ARP数据包进行分析,从而熟悉ARP数据包的结构,对ARP协议有更好的理解和认识。要求编写一程序,获取网络中的ARP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件。

    2.设计原理

    Ip数据报通过winpcap中的过滤器编译设置后可以直接捕获出来,然后按照其首部不同字节数,利用结构体将IP数据报首部内容分别解析出来,并写入日志文件中。IP数据包首部部分如下所示:

    在这里插入图片描述

    ARP主要作用就是通过IP地址来获取MAC地址。那么怎样获取呢?本机向局域网内主机发送ARP包,ARP包内包含了目的IP,源IP,目的MAC,源MAC,其中目的MAC地址为广播地址,FF-FF-FF-FF-FF-FF,即向局域网内所有主机发送一个ARP请求,那么其他主机收到这个请求之后则会向请求来源返回一个数据包。在这个返回的数据包中包含了自身的MAC地址。那么本机收到这些返回的数据包进行解析之后便会得到局域网内所有主机的MAC地址了。

    3.程序设计流程

    在这里插入图片描述

    4.核心代码:

    (1)编译和设置过滤器:

    //编译过滤器
        if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)
        {
            fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
    
        //设置过滤器
        if (pcap_setfilter(adhandle, &fcode) < 0)
        {
            fprintf(stderr, "\nError setting the filter.\n");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
    }
    
    

    (2)解析ARP数据包,并写入日志文档

    ofstream fout(argv[1],ios::app); //打开参数二,即日志记录文件,使用ios::app模式,新内容只会写到文件的后面
    	int k=1;
        /* 获取数据包 */
        while ((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0) {
            if (res == 0)
                /* 超时时间到 */
                continue;
    
            //解析ARP包
            ArpHeader* arph = (ArpHeader *)(pkt_data + 14);
    		printf("----------------------------解析到的第%d个ARP数据包-----------------------------\n",k);
    		fout<<"----------------------------解析到的第"<<k<<"个ARP数据包-----------------------------\n";
    
            //类型 
            printf("报文类型:");
            if (arph->op == 256){
                printf("请求报文\t");
    		fout<<"请求报文\t";
    		}
            else{
                printf("应答报文\t");
    			fout<<"应答报文\t";
    		}
    
            //长度
            printf("长度(B):%d\t", header->len);
    		fout<<"长度(B):"<<header->len<<"\t";
    
            //时间
            /* 将时间戳转换成可识别的格式 */
            local_tv_sec = header->ts.tv_sec;
            ltime = localtime(&local_tv_sec);
            strftime(timestr, sizeof timestr, "%H:%M:%S", ltime);
    
            printf("时间:%s\n", timestr);
    		fout<<"时间:"<<timestr<<"\n";
    
            //输出源IP
            printf("源IP:");
            for (i = 0; i < 3; i++)
            {
                printf("%d.", arph->sip[i]);
    			fout<<int(arph->sip[i]);
            }
            printf("%d\t", arph->sip[3]);
    		fout<<"源IP:"<<int(arph->sip[3])<<"\t";
    
            //输出目的IP
            printf("目的IP:");
            for (i = 0; i < 3; i++)
            {
                printf("%d.", arph->dip[i]);
    			fout<<"目的IP:"<<int(arph->dip[i])<<".";
    
            }
            printf("%d\n", arph->dip[3]);
    		fout<<int(arph->dip[2])<<"\n";
    
            //输出源MAC
            printf("源MAC:");
            for (i = 0; i < 5; i++)
            {
                printf("%02x-", arph->smac[i]);
    			fout<<int(arph->smac[i])<<"-";
            }
            printf("%02x\t", arph->smac[5]);
    		fout<<"源MAC:"<<int(arph->smac[5])<<"\t";
    
            //输出目的MAC
            printf("目的MAC:");
            for (i = 0; i < 5; i++)
            {
                printf("%02x-", *(pkt_data + i));
    			fout<<int(*(pkt_data + i))<<"-";
            }
            printf("%02x\n", *(pkt_data + 5));
    		fout<<"目的MAC:"<<int(*(pkt_data + 5))<<"\n";  
    		k++;
        }
    
        if (res == -1) {   //接收ARP包出错
            printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
            return -1;
        }
    
        return 0;
    }
    
    

    (3)解析IP数据包:

    void ip_protool_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
    {
      struct ip_header *ip_protocol;
      u_int header_length = 0;
      u_int offset;
      u_char tos;
      u_int16_t checksum;
      u_int ip_len;                      //ip首部长度
      u_int ip_version;  
      TcpHeader *tcp;                  //TCP头      
      //MAC首部是14位的,加上14位得到IP协议首部
      ip_protocol = (struct ip_header *) (packet_content+14);
      
      ip_len = (ip_protocol->Version_HLen & 0xf) *4;
      ip_version = ip_protocol->Version_HLen>>4;
      tcp = (TcpHeader *)((u_char *)ip_protocol+ip_len);
    
      checksum =ntohs(ip_protocol->ip_checksum);
      tos = ip_protocol->ip_tos;
      offset = ntohs(ip_protocol->ip_off);
      printf("---------IP协议---------\n");
      printf("版本号:%d\n", ip_version);
      printf("首部长度:%d\n",ip_len);
      printf("服务质量:%d\n",tos);
      printf("总长度:%d\n",ntohs(ip_protocol->ip_length));
      printf("标识:%d\n",ntohs(ip_protocol->ip_id));
      printf("偏移:%d\n",(offset & 0x1fff) * 8);
      printf("生存时间:%d\n",ip_protocol->ip_ttl);
      printf("协议类型:%d\n",ip_protocol->ip_protocol);
      switch (ip_protocol->ip_protocol)
      {
           case 1: printf("上层协议是ICMP协议\n");break;
           case 2: printf("上层协议是IGMP协议\n");break;
           case 6: printf("上层协议是TCP协议\n");break;
           case 17: printf("上层协议是UDP协议\n");break;
           default:break;
      }
    
      printf("检验和:%d\n",checksum);
      printf("源IP地址:%s\n", inet_ntoa(ip_protocol->ip_souce_address));
      printf("目的地址:%s\n", inet_ntoa(ip_protocol->ip_destination_address));
      }
    }
    
    

    5.结果及分析

    1、运行结果:

    解析ARP数据包并写入日志文档:

    在这里插入图片描述

    日志文档:

    在这里插入图片描述

    解析IP数据包:

    在这里插入图片描述

    日志文件:

    在这里插入图片描述

    6.完整代码如下:

    6.1 解析ARP数据包

    #include<fstream.h>
    #include<conio.h>  //使用_getch()
    #include "pcap.h"
    #include <string>
    #pragma comment(lib,"wpcap.lib")
    #pragma comment(lib,"packet.lib")
    #pragma comment(lib,"ws2_32.lib")
    struct ArpHeader
    {
        unsigned short hdtyp;   //硬件类型
        unsigned short protyp;   //协议类型
        unsigned char hdsize;   //硬件地址长度
        unsigned char prosize;   //协议地址长度
        unsigned short op;   //操作类型,ARP请求(1),ARP应答(2),RARP请求(3),RARP应答(4)。
        u_char smac[6];   //源MAC地址
        u_char sip[4];   //源IP地址
        u_char dmac[6];   //目的MAC地址
        u_char dip[4];   //目的IP地址
    };
    
    int main(int argc,char *argv[])
    {
       /*	if(argc!=2){
    		printf("参数不对,应该为exe文件+日志文件名");
    		printf("按任意键退出");
    		_getch();
    	}*/
        pcap_if_t *alldevs;   //所有网络适配器  
        pcap_if_t *d;   //选中的网络适配器 
        int inum;   //选择网络适配器
        int i = 0;   //for循环变量
        pcap_t *adhandle;   //打开网络适配器,捕捉实例,是pcap_open返回的对象
        char errbuf[PCAP_ERRBUF_SIZE];   //错误缓冲区,大小为256
        int res;   //抓包函数pcap_next_ex返回值,1-成功、0:获取报文超时、-1:发生错误、-2: 获取到离线记录文件的最后一个报文
        u_int netmask;    //子网掩码
        //ether proto protocol:如果数据包属于某些以太协议(protocol)类型, 则与此对应的条件表达式为真,协议字段可以是ARP
        char packet_filter[] = "ether proto \\arp";   //要抓取的包的类型,这里是抓取ARP包;
        struct bpf_program fcode;   //pcap_compile所调用的结构体
        struct tm *ltime;   //和时间处理有关的变量 
        char timestr[16];   //和时间处理有关的变量
        time_t local_tv_sec;    //和时间处理有关的变量
        struct pcap_pkthdr *header;   //接收到的数据包的头部
        const u_char *pkt_data;    //接收到的数据包的内容
    
        /* 获取本机设备列表 */
        if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
        {
            fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
            exit(1);
        }
    
        /* 打印列表 */
        for (d = alldevs; d; d = d->next)
        {
            printf("%d. %s", ++i, d->name);
            if (d->description)
                printf(" (%s)\n", d->description);
            else
                printf(" (No description available)\n");
        }
    
        if (i == 0)
        {
            printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
            return -1;
        }
    
        printf("Enter the interface number (1-%d):", i);
        scanf("%d", &inum);
    
        if (inum < 1 || inum > i)
        {
            printf("\nInterface number out of range.\n");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
    
        /* 跳转到已选中的适配器 */
        for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
    
        /* 打开设备 */
        if ((adhandle = pcap_open(d->name,          // 设备名
            65536,            // 要捕捉的数据包的部分 
                              // 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
            PCAP_OPENFLAG_PROMISCUOUS,    // 混杂模式
            1000,             // 读取超时时间
            NULL,             // 远程机器验证
            errbuf            // 错误缓冲池
            )) == NULL)
        {
            fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
            /* 释放设列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
    
        /* 检查数据链路层,为了简单,我们只考虑以太网 */
        if (pcap_datalink(adhandle) != DLT_EN10MB)
        {
            fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
    
        if (d->addresses != NULL)
            /* 获得接口第一个地址的掩码 */
            netmask = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
        else
            /* 如果接口没有地址,那么我们假设一个C类的掩码 */
            netmask = 0xffffff;
    
        //编译过滤器
        if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)
        {
            fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
    
        //设置过滤器
        if (pcap_setfilter(adhandle, &fcode) < 0)
        {
            fprintf(stderr, "\nError setting the filter.\n");
            /* 释放设备列表 */
            pcap_freealldevs(alldevs);
            return -1;
        }
    
        printf("\nlistening on %s...\n", d->description);
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
    
        /*以上代码在WinPcap开发文档中都可以找到,解析ARP包的代码自己编写*/
    	ofstream fout(argv[1],ios::app); //打开参数二,即日志记录文件,使用ios::app模式,新内容只会写到文件的后面
    	int k=1;
        /* 获取数据包 */
        while ((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0) {
            if (res == 0)
                /* 超时时间到 */
                continue;
    
            //解析ARP包
            ArpHeader* arph = (ArpHeader *)(pkt_data + 14);
    		printf("----------------------------解析到的第%d个ARP数据包-----------------------------\n",k);
    		fout<<"----------------------------解析到的第"<<k<<"个ARP数据包-----------------------------\n";
    
            //类型 
            printf("报文类型:");
            if (arph->op == 256){
                printf("请求报文\t");
    		fout<<"请求报文\t";
    		}
            else{
                printf("应答报文\t");
    			fout<<"应答报文\t";
    		}
    
            //长度
            printf("长度(B):%d\t", header->len);
    		fout<<"长度(B):"<<header->len<<"\t";
    
            //时间
            /* 将时间戳转换成可识别的格式 */
            local_tv_sec = header->ts.tv_sec;
            ltime = localtime(&local_tv_sec);
            strftime(timestr, sizeof timestr, "%H:%M:%S", ltime);
    
            printf("时间:%s\n", timestr);
    		fout<<"时间:"<<timestr<<"\n";
    
            //输出源IP
            printf("源IP:");
            for (i = 0; i < 3; i++)
            {
                printf("%d.", arph->sip[i]);
    			fout<<int(arph->sip[i]);
            }
            printf("%d\t", arph->sip[3]);
    		fout<<"源IP:"<<int(arph->sip[3])<<"\t";
    
            //输出目的IP
            printf("目的IP:");
            for (i = 0; i < 3; i++)
            {
                printf("%d.", arph->dip[i]);
    			fout<<"目的IP:"<<int(arph->dip[i])<<".";
    
            }
            printf("%d\n", arph->dip[3]);
    		fout<<int(arph->dip[2])<<"\n";
    
            //输出源MAC
            printf("源MAC:");
            for (i = 0; i < 5; i++)
            {
                printf("%02x-", arph->smac[i]);
    			fout<<int(arph->smac[i])<<"-";
            }
            printf("%02x\t", arph->smac[5]);
    		fout<<"源MAC:"<<int(arph->smac[5])<<"\t";
    
            //输出目的MAC
            printf("目的MAC:");
            for (i = 0; i < 5; i++)
            {
                printf("%02x-", *(pkt_data + i));
    			fout<<int(*(pkt_data + i))<<"-";
            }
            printf("%02x\n", *(pkt_data + 5));
    		fout<<"目的MAC:"<<int(*(pkt_data + 5))<<"\n";  
    		k++;
        }
    
        if (res == -1) {   //接收ARP包出错
            printf("Error reading the packets: %s\n", pcap_geterr(adhandle));
            return -1;
        }
    
        return 0;
    }
    
    

    解析IP数据包

    //捕获网络数据包的C++程序
    //可以获得数据包长度、通过以太网类型确定上层协议、源以太网地址和目的以太网地址!
    #include "pcap.h"
    #include<winsock2.h>
    #include<fstream.h>
    #pragma comment(lib,"wpcap.lib")
    #pragma comment(lib,"packet.lib")
    #pragma comment(lib,"ws2_32.lib")
    void packet_handler(u_char *param,const struct pcap_pkthdr *header,const u_char *pcap_data);
    #define IPTOSBUFFERS 12
    void ifprint(pcap_if_t *d);
    char * iptos(u_long in);
    int i = 0;
    /*以下是以太网协议格式*/
    struct ether_header
    {
      u_int8_t ether_dhost[6]; //目的Mac地址
      u_int8_t ether_shost[6]; //源Mac地址
      u_int16_t ether_type;    //协议类型
    };
     
    struct ip_header
    {
    unsigned char Version_HLen;   //版本信息4位 ,头长度4位 1字节
      u_int8_t    ip_tos;
      u_int16_t   ip_length;
      u_int16_t   ip_id;
      u_int16_t   ip_off;
      u_int8_t    ip_ttl;
      u_int8_t    ip_protocol;
      u_int16_t   ip_checksum;
      struct in_addr ip_souce_address;
      struct in_addr ip_destination_address;
    };
     
    //TCP头部结构体,共20字节
    struct TcpHeader
    {
        unsigned short SrcPort;                        //源端口号  2字节
        unsigned short DstPort;                        //目的端口号 2字节
        unsigned int SequenceNum;               //序号  4字节
        unsigned int Acknowledgment;         //确认号  4字节
        unsigned char HdrLen;                         //首部长度4位,保留位6位 共10位
        unsigned char Flags;                          //标志位6位
        unsigned short AdvertisedWindow;  //窗口大小16位 2字节
        unsigned short Checksum;                  //校验和16位   2字节
        unsigned short UrgPtr;						  //紧急指针16位   2字节
    };
     
    void ip_protool_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
    {
      struct ip_header *ip_protocol;
      u_int header_length = 0;
      u_int offset;
      u_char tos;
      u_int16_t checksum;
      u_int ip_len;                      //ip首部长度
      u_int ip_version;  
      TcpHeader *tcp;                  //TCP头          
      //MAC首部是14位的,加上14位得到IP协议首部
      ip_protocol = (struct ip_header *) (packet_content+14);
      
      ip_len = (ip_protocol->Version_HLen & 0xf) *4;
      ip_version = ip_protocol->Version_HLen>>4;
      tcp = (TcpHeader *)((u_char *)ip_protocol+ip_len);
    
      checksum =ntohs(ip_protocol->ip_checksum);
      tos = ip_protocol->ip_tos;
      offset = ntohs(ip_protocol->ip_off);
      ofstream fout;
      fout.open("解析IP数据包.txt",ios::app); //打开日志记录文件,使用ios::app模式,新内容只会写到文件的后面
    
      printf("---------IP协议---------\n");
      fout<<"---------IP协议---------\n";
      printf("版本号:%d\n", ip_version);
      fout<<"版本号:"<<ip_version<<"\n";
      printf("首部长度:%d\n",ip_len);
      fout<<"首部长度:"<<ip_len<<"\n";
      printf("服务质量:%d\n",tos);
      fout<<"服务质量:"<<tos<<"\n";
      printf("总长度:%d\n",ntohs(ip_protocol->ip_length));
      fout<<"总长度:"<<ntohs(ip_protocol->ip_length)<<"\n";
      printf("标识:%d\n",ntohs(ip_protocol->ip_id));
      fout<<"标识:"<<ntohs(ip_protocol->ip_id)<<"\n";
      printf("偏移:%d\n",(offset & 0x1fff) * 8);
      int x;
      x=(offset & 0x1fff) * 8;
      fout<<"偏移:"<<x<<"\n";
      printf("生存时间:%d\n",ip_protocol->ip_ttl);
      fout<<"生存时间:"<<ip_protocol->ip_ttl<<"\n";
      printf("协议类型:%d\n",ip_protocol->ip_protocol);
      int y;
      y=ip_protocol->ip_protocol;
      fout<<"协议类型:"<<y<<"\n";
      switch (ip_protocol->ip_protocol)
      {
           case 1: printf("上层协议是ICMP协议\n");break;
           case 2: printf("上层协议是IGMP协议\n");break;
           case 6: printf("上层协议是TCP协议\n");break;
           case 17: printf("上层协议是UDP协议\n");break;
           default:break;
      }
    
      printf("检验和:%d\n",checksum);
      fout<<"检验和:"<<checksum<<"\n";
      printf("源IP地址:%s\n", inet_ntoa(ip_protocol->ip_souce_address));
      fout<<"源IP地址:"<<inet_ntoa(ip_protocol->ip_souce_address)<<"\n";
      printf("目的地址:%s\n", inet_ntoa(ip_protocol->ip_destination_address));
      fout<<"目的地址:"<<inet_ntoa(ip_protocol->ip_destination_address)<<"\n";
      fout.close();	
    }
     
    void ethernet_protocol_packet_callback(u_char *argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
    {
      u_short ethernet_type;
      struct ether_header *ethernet_protocol;
      u_char *mac_string;
      static int packet_number = 1;
      
     ethernet_protocol=(struct ether_header*)packet_content;//获得数据包内容
      ethernet_type=ntohs(ethernet_protocol->ether_type);//获得以太网类型
      if(ethernet_type==0x0800)//继续分析IP协议
      {
    
         ip_protool_packet_callback (argument,packet_header,packet_content);
      }
     // printf("----------------------------------------------\n");
      packet_number++;
    
    }
     
    int main(int argc,char *argv[])
    // {
    //      pcap_t* pcap_handle; //winpcap句柄
    //      char error_content[PCAP_ERRBUF_SIZE]; //存储错误信息
    //      bpf_u_int32 net_mask; //掩码地址
    //      bpf_u_int32 net_ip;  //网络地址
    //      char *net_interface;  //网络接口
    //      struct bpf_program bpf_filter;  //BPF过滤规则
    //      char bpf_filter_string[]="ip"; //过滤规则字符串,只分析IPv4的数据包
    //      net_interface=pcap_lookupdev(error_content); //获得网络接口
    //      pcap_lookupnet(net_interface,&net_ip,&net_mask,error_content); //获得网络地址和掩码地址
    //      pcap_handle=pcap_open_live(net_interface,BUFSIZ,1,0,error_content); //打开网络接口
    //      pcap_compile(pcap_handle,&bpf_filter,bpf_filter_string,0,net_ip); //编译过滤规则
    //      pcap_setfilter(pcap_handle,&bpf_filter);//设置过滤规则
    //      if (pcap_datalink(pcap_handle)!=DLT_EN10MB) //DLT_EN10MB表示以太网
    //          return 0;
    //      pcap_loop(pcap_handle,10,ethernet_protocol_packet_callback,NULL); //捕获10个数据包进行分析
    //      pcap_close(pcap_handle);
    //      return 0;
    // }
    {
    	pcap_if_t * alldevs;
    	pcap_if_t * d;
    	int inum;
    	pcap_t * adhandle;
    	char errbuf[PCAP_ERRBUF_SIZE];
    	/*取得列表*/
    	if(pcap_findalldevs(&alldevs,errbuf) == -1)
    	{
    		exit(1);
    	}
    	/*输出列表*/
    	for(d=alldevs;d != NULL;d=d->next)
    	{
    		ifprint(d);
    	}
    	if(i==0)
    	{
     
    		printf("\nNo interfaces found!Make sure WinPcap is installed.\n");
    		char c = getchar();
    		return -1;
    	}
    	printf("Enter the interface number (1-%d):",i);
    	scanf("%d",&inum);
    	if(inum <1 || inum >i)
    	{
    		printf("\nInterface number out of range.\n");
    		pcap_freealldevs(alldevs);
    		char c = getchar();
    		return -1;
    	}
    	
    	//转到选择的设备
    	for (d = alldevs,i=0;i <inum-1;d=d->next,i++);
    	//打开失败
    	if ((adhandle=pcap_open_live(d->name,65536,1,1000,errbuf))==NULL)
    	{
    		fprintf(stderr,"\nUnable to open the adapter.%s is not supported by WinPcap\n");
    		pcap_freealldevs(alldevs);
    		char c = getchar();
    		return -1;
    	}
    	printf("\nlistening on %s...\n",d->description);
    	//释放列表
    	pcap_freealldevs(alldevs);
    	//开始捕捉
    	//pcap_loop(adhandle,0,ip_protool_packet_callback,NULL);
    	pcap_loop(adhandle,0,ethernet_protocol_packet_callback,NULL);
    	char c = getchar();
    	return 0;
    }
    void ifprint(pcap_if_t *d)
    {
    	pcap_addr_t *a;
    	printf("%d.%s",++i,d->name);
    	if(d->description)
    	{
    		printf("\tDescription:(%s)\n",d->description);
    	}else{
    		printf("\t(No description available)\n");
    	}
    	printf("\tLoopback:%s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
    	for (a=d->addresses;a != NULL;a=a->next)
    	{
    		printf("\tAddress Family:#%d\n",a->addr->sa_family);
    		switch (a->addr->sa_family)
    		{
    		case AF_INET:
    			printf("\tAddress Family Name:AF_INET\n");
    			if(a->addr)
    			{
    				printf("\tAddress:%s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
    			}
    			if(a->netmask)
    			{
    				printf("\tNetmask:%s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
    			}
    			if(a->broadaddr)
    			{
    				printf("\tBroadcast Address:%s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
    			}
    			if(a->dstaddr)
    			{
    				printf("\tDestination Address:%s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
    			}
    			break;
    		default:
    			printf("\tAddressFamilyName:Unknown\n");
    			break;
    		}
    	}
    }
    char * iptos(u_long in)
    { 
    	static char output[IPTOSBUFFERS][3*4+3+1];
    	static short which;
    	u_char *p; 
    	p = (u_char *)&in;
    	which=(which+1==IPTOSBUFFERS?0:which+1); 
    	sprintf(output[which],"%d.%d.%d.%d",p[0],p[1],p[2],p[3]);
    	return output[which];
    }
    void packet_handler(u_char *param,const struct pcap_pkthdr *header,const u_char *pcap_data)
    {
    	struct tm * ltime;
    	char timestr[16];
    	ltime = localtime(&header->ts.tv_sec);
    	strftime(timestr,sizeof(timestr),"%H:%M:%S",ltime);
    	printf("%s, %.6d len:%d\n",timestr,header->ts.tv_usec,header->len);
    }
    
    展开全文
  • 在对IP层的工作原理有一定的了解的基础上,利用所掌握的编程语言,设计一个解析IP数据包的程序,并根据这个程序,得出和说明IP数据包的结构以及IP协议的相关问题,从而达到对IP层的工作原理一斤相关知识有一个更好更...
  • 包含源代码的计算机网络课设——解析IP数据包部分

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 100,024
精华内容 40,009
关键字:

解析ip数据包