本帖最后由 VisualEleven 于 2012-06-01 08:01:12 编辑

解决方案 »

  1.   

    #define APP_NAME        "sniffex"
    #define APP_DESC        "Sniffer example using libpcap"
    #define APP_COPYRIGHT    "Copyright (c) 2005"
    #define APP_DISCLAIMER    "THERE IS ABSOLUTELY NO WARRANTY FOR THIS PROGRAM."#define HAVE_REMOTE
    我的程序是这样写的:
    #include <pcap.h>
    #include <stdio.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #ifdef WIN32
    #include <winsock2.h> 
    #include <iostream>
    // 告诉连接器与WS2_32库连接
    #pragma comment(lib,"WS2_32.lib")
    #pragma warning(disable: 4996)
    #else
    #include <ctype.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #endif
    using namespace std;   
    /* default snap length (maximum bytes per packet to capture) */
    #define SNAP_LEN 1518
    /*分析:6字节目的地址+6字节源地址+2字节帧类型+最大1500字上层数据+4字节CRC校验*/
    /* ethernet headers are always exactly 14 bytes [1] */
    #define SIZE_ETHERNET 14/* Ethernet addresses are 6 bytes */
    #define ETHER_ADDR_LEN    6/* Ethernet header */
    struct sniff_ethernet {
            u_char ether_dhost[ETHER_ADDR_LEN]; /* destination host address */
            u_char ether_shost[ETHER_ADDR_LEN]; /* source host address */
            u_short ether_type; /* IP? ARP? RARP? etc */
    };/* IP header */
    struct sniff_ip {
            u_char ip_vhl; /* version << 4 | header length >> 2 */
            u_char ip_tos; /* type of service */
            u_short ip_len; /* total length */
            u_short ip_id; /* identification */
            u_short ip_off; /* fragment offset field */
            #define IP_RF 0x8000 /* reserved fragment flag */
            #define IP_DF 0x4000 /* dont fragment flag */
            #define IP_MF 0x2000 /* more fragments flag */
            #define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
            u_char ip_ttl; /* time to live */
            u_char ip_p; /* protocol */
            u_short ip_sum; /* checksum */
            struct in_addr ip_src,ip_dst; /* source and dest address */
    };
    #define IP_HL(ip) (((ip)->ip_vhl) & 0x0f)//解析首部长度
    #define IP_V(ip) (((ip)->ip_vhl) >> 4)//解析首部版本号/* TCP header */
    typedef u_int tcp_seq;struct sniff_tcp {
            u_short th_sport; /* source port */
            u_short th_dport; /* destination port */
            tcp_seq th_seq; /* sequence number */
            tcp_seq th_ack; /* acknowledgement number */
            u_char th_offx2; /* data offset, rsvd */
    #define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
            u_char th_flags;
            #define TH_FIN 0x01
            #define TH_SYN 0x02
            #define TH_RST 0x04
            #define TH_PUSH 0x08
            #define TH_ACK 0x10
            #define TH_URG 0x20
            #define TH_ECE 0x40
            #define TH_CWR 0x80
            #define TH_FLAGS (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
            u_short th_win; /* window */
            u_short th_sum; /* checksum */
            u_short th_urp; /* urgent pointer */
    };void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);void print_payload(const u_char *payload, int len);void print_hex_ascii_line(const u_char *payload, int len, int offset);void print_app_banner(void);void print_app_usage(void);
    std::string IpToStr(const sockaddr *addr);
    void PrintAdapterInfo(pcap_if_t* pAdapter);// 将sockaddr*类型的IP转换成字符串类型的IP地址
    std::string IpToStr(const sockaddr *addr)
    {
    std::string s;
    s = inet_ntoa((*(sockaddr_in*)addr).sin_addr);
    return s;
    }
    // 输出每个网卡的信息
    void PrintAdapterInfo(pcap_if_t* pAdapter)
    {
    printf("名字:%s\n", pAdapter->name);
    if (pAdapter->description)
    printf("描述:(%s)\n", pAdapter->description);
    else
    printf(" (没有相关的描述信息)\n"); pcap_addr *p = pAdapter->addresses;  // 得到指向地址结构的指针
    // 输出地址信息
    while(p != NULL)
    {
    printf("IP地址:%s\n", IpToStr(p->addr).c_str());
    printf("子网掩码:%s\n", IpToStr(p->netmask).c_str());
    printf("广播地址:%s\n", IpToStr(p->broadaddr).c_str());
    p = p->next;
    }
    printf("\n\n");
    }
    /*
     * app name/banner
     */
    void
    print_app_banner(void)
    {    printf("%s - %s\n", APP_NAME, APP_DESC);
        printf("%s\n", APP_COPYRIGHT);
        printf("%s\n", APP_DISCLAIMER);
        printf("\n");return;
    }/*
     * print help text
     */
    void
    print_app_usage(void)
    {    printf("Usage: %s [interface]\n", APP_NAME);
        printf("\n");
        printf("Options:\n");
        printf(" interface Listen on <interface> for packets.\n");
        printf("\n");return;
    }/*
     * print data in rows of 16 bytes: offset hex ascii
     *
     * 00000 47 45 54 20 2f 20 48 54 54 50 2f 31 2e 31 0d 0a GET / HTTP/1.1..
     */
    void
    print_hex_ascii_line(const u_char *payload, int len, int offset)
    {    int i;
        int gap;
        const u_char *ch;    /* offset */
        printf("%05d ", offset);
        
        /* hex */
        ch = payload;
        for(i = 0; i < len; i++) {
            printf("%02x ", *ch);
            ch++;
            /* print extra space after 8th byte for visual aid */
            if (i == 7)
                printf(" ");
        }
        /* print space to handle line less than 8 bytes */
        if (len < 8)
            printf(" ");
        
        /* fill hex gap with spaces if not full line */
        if (len < 16) {
            gap = 16 - len;
            for (i = 0; i < gap; i++) {
                printf(" ");
            }
        }
        printf(" ");
        
        /* ascii (if printable) */
        ch = payload;
        for(i = 0; i < len; i++) {
            if (isprint(*ch))
                printf("%c", *ch);
            else
                printf(".");
            ch++;
        }    printf("\n");return;
    }/*
     * print packet payload data (avoid printing binary data)
     */
    void print_payload(const u_char *payload, int len)
    {    int len_rem = len;
        int line_width = 16;            /* number of bytes per line */
        int line_len;
        int offset = 0;                    /* zero-based offset counter */
        const u_char *ch = payload;       /* data fits on one line */
        if (len <= line_width) {
            print_hex_ascii_line(ch, len, offset);
            return;
        }    /* data spans multiple lines */
        for ( ;; ) {
            /* compute current line length */
            line_len = line_width % len_rem;
            /* print line */
            print_hex_ascii_line(ch, line_len, offset);
            /* compute total remaining */
            len_rem = len_rem - line_len;
            /* shift pointer to remaining bytes to print */
            ch = ch + line_len;
            /* add offset */
            offset = offset + line_width;
            /* check if we have line width chars or less */
            if (len_rem <= line_width) {
                /* print last line and get out */
                print_hex_ascii_line(ch, len_rem, offset);
                break;
            }
        }return;
    }/*
     * dissect/print packet
     */
    void
    got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
    {    static int count = 1; /* packet counter */
        
        /* declare pointers to packet headers */
        const struct sniff_ethernet *ethernet; /* The ethernet header [1] */
        const struct sniff_ip *ip; /* The IP header */
        const struct sniff_tcp *tcp; /* The TCP header */
        const u_char *payload; /* Packet payload */    int size_ip;
        int size_tcp;
        int size_payload;
        
        printf("\nPacket number %d:\n", count);
        count++;
        printf("打印以太帧!\n");
    const u_char *ptr=packet;
    int i=0;
    for(i=0;i<SIZE_ETHERNET+8;i++)
    {
    printf("[%02d]:%x ",i,*ptr);
    ptr++;
    }
    /*
    IP包头开始部分的第一个字节应该是45,4表示协议版本是IPV4,5表示IP包头部是5个32bit长,也就是20个字节
    */
        printf("\n以太帧打印完毕\n");
        /* define ethernet header */
        ethernet = (struct sniff_ethernet*)(packet);
        
        /* define/compute ip header offset */
        ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);//越过以太网首部,得到IP首部
        size_ip = IP_HL(ip)*4;/*IP包头长度单位为32Bit*/
        if (size_ip < 20) {
            printf(" * Invalid IP header length: %u bytes\n", size_ip);
            return;
        }    /* print source and destination IP addresses */
        printf(" From: %s\n", inet_ntoa(ip->ip_src));
        printf(" To: %s\n", inet_ntoa(ip->ip_dst));
        
        /* determine protocol */    
        switch(ip->ip_p) {
            case IPPROTO_TCP:
                printf(" Protocol: TCP\n");
                break;
            case IPPROTO_UDP:
                printf(" Protocol: UDP\n");
                return;
            case IPPROTO_ICMP:
                printf(" Protocol: ICMP\n");
                return;
            case IPPROTO_IP:
                printf(" Protocol: IP\n");
                return;
            default:
                printf(" Protocol: unknown\n");
                return;
        }
        
        /*
         * OK, this packet is TCP.
         */
        
        /* define/compute tcp header offset */
        tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);    //越过IP首部,得到TCP首部
        size_tcp = TH_OFF(tcp)*4;
        if (size_tcp < 20) {
            printf(" * Invalid TCP header length: %u bytes\n", size_tcp);
            return;
        }
        
        printf(" Src port: %d\n", ntohs(tcp->th_sport));
        printf(" Dst port: %d\n", ntohs(tcp->th_dport));
        
        /* define/compute tcp payload (segment) offset */
        payload = (u_char *)(packet + SIZE_ETHERNET + size_ip + size_tcp);
        //越过TCP首部得到净载荷数据
        
        /* compute tcp payload (segment) size */
        size_payload = ntohs(ip->ip_len) - (size_ip + size_tcp);
       
        /*
         * Print payload data; it might be binary, so don't just
         * treat it as a string.
         */
         printf(" Payload (%d bytes):\n", size_payload);
        if (size_payload > 0) {
            
            print_payload(payload, size_payload);
        }return;
    }
      

  2.   

    下面是main函数:int main(int argc, char **argv)
    {
        
        char errbuf[PCAP_ERRBUF_SIZE];        /* error buffer */
        pcap_t *handle;                /* packet capture handle */
    int i=0;
    int inum;
    pcap_if_t *alldevs;
    pcap_if_t *dev;
    char filter_exp[] = "tcp";        /* filter expression [3] */
        struct bpf_program fp;            /* compiled filter program (expression) */
        bpf_u_int32 mask;            /* subnet mask */
        bpf_u_int32 net;            /* ip */
        int num_packets = 10;            /* number of packets to capture */
     /* 这个API用来获得网卡 的列表 */
        if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
          {
               fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
               exit(1);
          }   
    /* 显示列表的响应字段的内容 */
        for(dev=alldevs;dev;dev=dev->next)
          {
                printf("%d. %s", ++i, dev->name);
                if (dev->description)
                    {
    printf("\n\t\tDescription: (%s)\n", dev->description);
    PrintAdapterInfo(dev);  // 输出每个网卡信息
    }
                else                printf(" (No description available)\n");
          }
        //没有找到相关设备
       if(i==0)
            {
                printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
                return 0;
            } 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(dev=alldevs, i=0; i< inum-1 ;dev=dev->next, i++);     print_app_banner(); 
        
        /* get network number and mask associated with capture device */
    /*
    *函数:pcap_lookupnet()
    *函数原型:int pcap_lookupnet(char *device, bpf_u_int32 *netp,bpf_u_int32 *maskp, char *errbuf) ;
    *函数作用:获得指定网络设备的网络的网络号和掩码。netp和maskp参数都是bpf_u_u_int32指针,用于存储网络设备IP地址与子网掩码。如果函数出错,则返回-1,t同时errbuf中存
    *放相关的出错信息
    */
        if (pcap_lookupnet(dev->name, &net, &mask, errbuf) == -1) {
            fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
             dev, errbuf);
            net = 0;
            mask = 0;
        }    /* print capture info */
        printf("Device: %s\n", dev->name);
        printf("Number of packets: %d\n", num_packets);
        printf("Filter expression: %s\n", filter_exp);

        /* open capture device */
    /*
    *函数:pcap_open_live
    *函数原型:pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) ;
    *函数作用:获取用于捕获网络数据包的数据包捕获描述字。device参数指定打开的网络设备名,snaplen参数指定捕获数据的最大字节数,promise指定是否将网络接口设置于混杂模式;to_ms
    *参数指定超时时间(毫秒),通常出于效率考虑,可以将该值的值设置得比较大,但是当对响应时间要求比较高式,应该将该值设置的比较小;ebuf参数则仅仅在pcap_open_live()函数出错式返回NULL时,用于存放出错信息。
    *若函数执行成功,则返回可用的数据包捕获描述字,否则返回NULL,同时在ebuf中存放错误的信息。
    */
        handle = pcap_open_live(dev->name, SNAP_LEN,1, 1000, errbuf);
        if (handle == NULL) {
    fprintf(stderr, "Couldn't open device %s: %s\n", dev->name, errbuf);
            exit(EXIT_FAILURE);
        }    /* make sure we're capturing on an Ethernet device [2] */
    /*
    *函数:pcap_datalink
    *函数原型:int pcap_datalink(pcap_t *p); 
    *函数作用:返回数据链路层类型,例如DLT_EN10MB。 
    */
        if (pcap_datalink(handle) != DLT_EN10MB) {
    fprintf(stderr, "%s is not an Ethernet\n", dev->name);
            exit(EXIT_FAILURE);
        }    /* compile the filter expression */
    /*
    *函数:pcap_compile
    *函数原型:int pcap_compile(pcap_t *p, struct bpf_program *fp,char *str, int optimize, bpf_u_int32 netmask) ;
    *函数作用:将指定的规则编译到过滤器中,其中参数p是描述字,fo是一个bpf_program结构的指针,在pcap_compile()函数中被赋值,optimize参数控制结果代码的优化,netmask参数指定
    *本地网络的网络掩码。若函数执行失败,会返回-1,成功时返回0。
    */
        if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
            fprintf(stderr, "Couldn't parse filter %s: %s\n",
             filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }    /* apply the compiled filter */
    /*
    *函数:pcap_setfilter
    *函数原型:int pcap_setfilter(pcap_t *p, struct bpf_program *fp);
    *函数作用:设定一个过滤程序,其中参数p是描述字,fp参数bpf_program结构指针,通常取自pcap_compile()函数调用。
    *若函数执行成功,则返回0,失败则返回-1。
    */
        if (pcap_setfilter(handle, &fp) == -1) {
            fprintf(stderr, "Couldn't install filter %s: %s\n",
             filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }    /* now we can set our callback function */
    /*
    *函数:pcap_loop
    *函数原型:int pcap_loop(pcap_t *p, int cnt,pcap_handler callback, u_char *user);
    *函数作用:捕获并处理数据包,其中参数pp是描述字。
    *cnt参数指定函数返回前处理数据包的最大值
    *若cnt值为-1,表示在一个缓冲区中处理所有的数据包,
    *若cnt值为0,表示处理所有的数据包,或者出现错误。
    *callback参数指定一个带有三个参数的回调函数,这个函数原型是:
    *void call_back(u_char *,pcap_pkthdr*,u_char *);
    *这三个参数一个是从pcap_loop()函数传递过来的u_char指针,一个是pcap_pkthdr结构的指针,另一个是指示数据包大小的u_char指针。
    *如果成功则返回读取到的字节数,读取到EOF时则返回零值,出错时则返回-1,此时可以调用pcap_perror()或者pcap_geterr()函数获取错误信息。
    */
        pcap_loop(handle, num_packets, got_packet, NULL);    /* cleanup */
        pcap_freecode(&fp);
    /*
    *函数:pcap_close();
    *函数原型:void pcap_close(pcap_t *p) ;
    *函数作用:关闭网络设备,并释放资源
    */
        pcap_close(handle);    printf("\nCapture complete.\n"); return 0;
    }
      

  3.   

    int main(int argc, char **argv)
    {
        
        char errbuf[PCAP_ERRBUF_SIZE];        /* error buffer */
        pcap_t *handle;                /* packet capture handle */
    int i=0;
    int inum;
    pcap_if_t *alldevs;
    pcap_if_t *dev;
    char filter_exp[] = "tcp";        /* filter expression [3] */
        struct bpf_program fp;            /* compiled filter program (expression) */
        bpf_u_int32 mask;            /* subnet mask */
        bpf_u_int32 net;            /* ip */
        int num_packets = 10;            /* number of packets to capture */
     /* 这个API用来获得网卡 的列表 */
        if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
          {
               fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
               exit(1);
          }   
    /* 显示列表的响应字段的内容 */
        for(dev=alldevs;dev;dev=dev->next)
          {
                printf("%d. %s", ++i, dev->name);
                if (dev->description)
                    {
    printf("\n\t\tDescription: (%s)\n", dev->description);
    PrintAdapterInfo(dev);  // 输出每个网卡信息
    }
                else                printf(" (No description available)\n");
          }
        //没有找到相关设备
       if(i==0)
            {
                printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
                return 0;
            } 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(dev=alldevs, i=0; i< inum-1 ;dev=dev->next, i++);     print_app_banner(); 
        
        /* get network number and mask associated with capture device */
    /*
    *函数:pcap_lookupnet()
    *函数原型:int pcap_lookupnet(char *device, bpf_u_int32 *netp,bpf_u_int32 *maskp, char *errbuf) ;
    *函数作用:获得指定网络设备的网络的网络号和掩码。netp和maskp参数都是bpf_u_u_int32指针,用于存储网络设备IP地址与子网掩码。如果函数出错,则返回-1,t同时errbuf中存
    *放相关的出错信息
    */
        if (pcap_lookupnet(dev->name, &net, &mask, errbuf) == -1) {
            fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
             dev, errbuf);
            net = 0;
            mask = 0;
        }    /* print capture info */
        printf("Device: %s\n", dev->name);
        printf("Number of packets: %d\n", num_packets);
        printf("Filter expression: %s\n", filter_exp);

        /* open capture device */
    /*
    *函数:pcap_open_live
    *函数原型:pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) ;
    *函数作用:获取用于捕获网络数据包的数据包捕获描述字。device参数指定打开的网络设备名,snaplen参数指定捕获数据的最大字节数,promise指定是否将网络接口设置于混杂模式;to_ms
    *参数指定超时时间(毫秒),通常出于效率考虑,可以将该值的值设置得比较大,但是当对响应时间要求比较高式,应该将该值设置的比较小;ebuf参数则仅仅在pcap_open_live()函数出错式返回NULL时,用于存放出错信息。
    *若函数执行成功,则返回可用的数据包捕获描述字,否则返回NULL,同时在ebuf中存放错误的信息。
    */
        handle = pcap_open_live(dev->name, SNAP_LEN,1, 1000, errbuf);
        if (handle == NULL) {
    fprintf(stderr, "Couldn't open device %s: %s\n", dev->name, errbuf);
            exit(EXIT_FAILURE);
        }    /* make sure we're capturing on an Ethernet device [2] */
    /*
    *函数:pcap_datalink
    *函数原型:int pcap_datalink(pcap_t *p); 
    *函数作用:返回数据链路层类型,例如DLT_EN10MB。 
    */
        if (pcap_datalink(handle) != DLT_EN10MB) {
    fprintf(stderr, "%s is not an Ethernet\n", dev->name);
            exit(EXIT_FAILURE);
        }    /* compile the filter expression */
    /*
    *函数:pcap_compile
    *函数原型:int pcap_compile(pcap_t *p, struct bpf_program *fp,char *str, int optimize, bpf_u_int32 netmask) ;
    *函数作用:将指定的规则编译到过滤器中,其中参数p是描述字,fo是一个bpf_program结构的指针,在pcap_compile()函数中被赋值,optimize参数控制结果代码的优化,netmask参数指定
    *本地网络的网络掩码。若函数执行失败,会返回-1,成功时返回0。
    */
        if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
            fprintf(stderr, "Couldn't parse filter %s: %s\n",
             filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }    /* apply the compiled filter */
    /*
    *函数:pcap_setfilter
    *函数原型:int pcap_setfilter(pcap_t *p, struct bpf_program *fp);
    *函数作用:设定一个过滤程序,其中参数p是描述字,fp参数bpf_program结构指针,通常取自pcap_compile()函数调用。
    *若函数执行成功,则返回0,失败则返回-1。
    */
        if (pcap_setfilter(handle, &fp) == -1) {
            fprintf(stderr, "Couldn't install filter %s: %s\n",
             filter_exp, pcap_geterr(handle));
            exit(EXIT_FAILURE);
        }    /* now we can set our callback function */
    /*
    *函数:pcap_loop
    *函数原型:int pcap_loop(pcap_t *p, int cnt,pcap_handler callback, u_char *user);
    *函数作用:捕获并处理数据包,其中参数pp是描述字。
    *cnt参数指定函数返回前处理数据包的最大值
    *若cnt值为-1,表示在一个缓冲区中处理所有的数据包,
    *若cnt值为0,表示处理所有的数据包,或者出现错误。
    *callback参数指定一个带有三个参数的回调函数,这个函数原型是:
    *void call_back(u_char *,pcap_pkthdr*,u_char *);
    *这三个参数一个是从pcap_loop()函数传递过来的u_char指针,一个是pcap_pkthdr结构的指针,另一个是指示数据包大小的u_char指针。
    *如果成功则返回读取到的字节数,读取到EOF时则返回零值,出错时则返回-1,此时可以调用pcap_perror()或者pcap_geterr()函数获取错误信息。
    */
        pcap_loop(handle, num_packets, got_packet, NULL);    /* cleanup */
        pcap_freecode(&fp);
    /*
    *函数:pcap_close();
    *函数原型:void pcap_close(pcap_t *p) ;
    *函数作用:关闭网络设备,并释放资源
    */
        pcap_close(handle);    printf("\nCapture complete.\n"); return 0;
    }
      

  4.   

    原始套接字只能在IP层捕获数据包,除非机顶盒的网关设置为你的电脑的IP地址,不如是抓不到的;你要抓的数据可能在MAC层就已经丢弃了
      

  5.   

    给你个建议用winpcap自带的sample来抓,只是在loop的回调函数中把对应的信息打出来,看看是否含有你想抓的包.如果不行,再考试是否是winpcap的问题,如果有,那就是你的filter有问题或者是哪些细节了.
      

  6.   

    四楼和五楼的网友给出的建议相当中肯有效,我最后也发现了问题所在,特分享一下,原因在于通过HUB传过来的数据包是用PPPoE协议封装的,看字节打印可以发现,以太帧首部和IP首部(当然是以0x45打头啦)有8个字节的数据,说明这跟普通的数据封装不一样,通过查看以太帧的数据类型,发现其值是0x8864,指示该包是PPPoE的会话阶段,后面的问题就迎刃而解啦
      

  7.   

    四楼和五楼的网友给出的建议相当中肯有效,我最后也发现了问题所在,特分享一下,原因在于通过HUB传过来的数据包是用PPPoE协议封装的,看字节打印可以发现,以太帧首部和IP首部(当然是以0x45打头啦)有8个字节的数据,说明这跟普通的数据封装不一样,通过查看以太帧的数据类型,发现其值是0x8864,指示该包是PPPoE的会话阶段,后面的问题就迎刃而解啦