Linux 网络编程—— libpcap 详解

来源:互联网 发布:杜月笙 知乎 编辑:程序博客网 时间:2024/05/18 01:50

概述

libpcap 是一个网络数据包捕获函数库,功能非常强大,Linux 下著名的 tcpdump 就是以它为基础的。

             

libpcap主要的作用
1)捕获各种数据包,列如:网络流量统计。
2)过滤网络数据包,列如:过滤掉本地上的一些数据,类似防火墙。
3)分析网络数据包,列如:分析网络协议,数据的采集。
4)存储网络数据包,列如:保存捕获的数据以为将来进行分析。


libpcap 的安装



libpcap 的抓包框架

pcap_lookupdev():函数用于查找网络设备,返回可被 pcap_open_live() 函数调用的网络设备名指针。

pcap_lookupnet():函数获得指定网络设备的网络号和掩码。
pcap_open_live(): 函数用于打开网络设备,并且返回用于捕获网络数据包的数据包捕获描述字。对于此网络设备的操作都要基于此网络设备描述字。
pcap_compile(): 函数用于将用户制定的过滤策略编译到过滤程序中。
pcap_setfilter():函数用于设置过滤器。
pcap_loop():函数 pcap_dispatch() 函数用于捕获数据包,捕获后还可以进行处理,此外 pcap_next() 和 pcap_next_ex() 两个函数也可以用来捕获数据包。
pcap_close():函数用于关闭网络设备,释放资源。


利用 libpcap 函数库开发应用程序的基本步骤

1、打开网络设备

2、设置过滤规则

3、捕获数据

4、关闭网络设备

抓包详细步骤

首先要使用 libpcap,我们必须包含 pcap.h 头文件,可以在 /usr/local/include/pcap/pcap.h 找到,其中包含了每个类型定义的详细说明。



1、获取网络接口设备名

char *pcap_lookupdev(char *errbuf)

功能

得到可用的网络设备名指针

参数

errbuf 存放出错信息字符串,里面有个宏定义:PCAP_ERRBUF_SIZE,为错误缓冲区大小

返回值

成功返回设备名指针(第一个合适的网络接口的字符串指针);

失败返回 NULL,同时,errbuf 存放出错信息字符串。

实例如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. char error_content[PCAP_ERRBUF_SIZE] = {0}; // 出错信息  
  2. charchar *dev = pcap_lookupdev(error_content);  
  3. if(NULL == dev)  
  4. {  
  5.     printf(error_content);  
  6.     exit(-1);  
  7. }  


2、获取网络号和掩码

int pcap_lookupnet(    char *device,                     

bpf_u_int32 *netp, 

bpf_u_int32 *maskp,     

char *errbuf )

功能

获取指定网卡的 ip 地址,子网掩码

参数

device:网络设备名,为第一步获取的网络接口字符串(pcap_lookupdev() 的返回值 ),也可人为指定,如“eth0”。

netp:存放 ip 地址的指针,bpf_u_int32 为 32 位无符号整型

maskp:存放子网掩码的指针,bpf_u_int32 为 32 位无符号整型

errbuf:存放出错信息

返回值

成功返回 0,失败返回 -1

实例如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. char error_content[PCAP_ERRBUF_SIZE] = {0}; // 出错信息  
  2. charchar *dev = pcap_lookupdev(error_content);  
  3. if(NULL == dev)  
  4. {  
  5.     printf(error_content);  
  6.     exit(-1);  
  7. }  
  8.   
  9.   
  10. bpf_u_int32 netp = 0, maskp = 0;  
  11. pcap_t * pcap_handle = NULL;  
  12. int ret = 0;  
  13.   
  14. //获得网络号和掩码  
  15. ret = pcap_lookupnet(dev, &netp, &maskp, error_content);  
  16. if(ret == -1)  
  17. {  
  18.     printf(error_content);  
  19.     exit(-1);  
  20. }  

3、打开网络接口

pcap_t *pcap_open_live(  const char *device,

int snaplen,

int promisc,

int to_ms,

char *ebuf )

功能

打开一个用于捕获数据的网络接口

参数

device:网络接口的名字,为第一步获取的网络接口字符串(pcap_lookupdev() 的返回值 ),也可人为指定,如“eth0”。

snaplen:捕获数据包的长度,长度不能大于 65535 个字节。

promise:“1” 代表混杂模式,其它非混杂模式。什么为混杂模式,请看《原始套接字编程》。

to_ms:指定需要等待的毫秒数,超过这个数值后,获取数据包的函数就会立即返回(这个函数不会阻塞,后面的抓包函数才会阻塞)。0 表示一直等待直到有数据包到来。

ebuf:存储错误信息。

返回值

返回 pcap_t 类型指针,后面的所有操作都要使用这个指针

实例如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. char error_content[PCAP_ERRBUF_SIZE] = {0}; // 出错信息  
  2. charchar *dev = pcap_lookupdev(error_content);  // 获取网络接口  
  3. if(NULL == dev)  
  4. {  
  5.     printf(error_content);  
  6.     exit(-1);  
  7. }  
  8.   
  9. // 打开网络接口  
  10. pcap_t * pcap_handle = pcap_open_live(dev, 102410, error_content);  
  11. if(NULL == pcap_handle)  
  12. {  
  13.     printf(error_content);  
  14.     exit(-1);  
  15. }  


4、获取数据包

a)

const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)

功能

捕获一个网络数据包,收到一个数据包立即返回

参数

p:pcap_open_live()返回的 pcap_t 类型的指针
h:数据包头


pcap_pkthdr 类型的定义如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. struct pcap_pkthdr  
  2. {  
  3.     struct timeval ts; // 抓到包的时间  
  4.     bpf_u_int32 caplen; // 表示抓到的数据长度  
  5.     bpf_u_int32 len; // 表示数据包的实际长度  
  6. }  
len 和 caplen的区别:
因为在某些情况下你不能保证捕获的包是完整的,例如一个包长 1480,但是你捕获到 1000 的时候,可能因为某些原因就中止捕获了,所以 caplen 是记录实际捕获的包长,也就是 1000,而 len 就是 1480。 

返回值

成功返回捕获数据包的地址,失败返回 NULL

实例如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. const unsigned charchar *p_packet_content = NULL// 保存接收到的数据包的起始地址  
  2. pcap_t *pcap_handle = NULL;  
  3. struct pcap_pkthdr protocol_header;  
  4.   
  5. pcap_handle = pcap_open_live("eth0"102410,NULL);  
  6.   
  7. p_packet_content = pcap_next(pcap_handle, &protocol_header);   
  8. //p_packet_content  所捕获数据包的地址  
  9.           
  10. printf("Capture Time is :%s",ctime((const time_ttime_t *)&protocol_header.ts.tv_sec)); // 时间  
  11. printf("Packet Lenght is :%d\n",protocol_header.len);   // 数据包的实际长度  
  12.   
  13. // 分析以太网中的 源mac、目的mac  
  14. struct ether_header *ethernet_protocol = NULL;  
  15. unsigned charchar *p_mac_string = NULL;         // 保存mac的地址,临时变量  
  16.   
  17. ethernet_protocol = (struct ether_header *)p_packet_content;  //struct ether_header 以太网帧头部  
  18.   
  19. p_mac_string = (unsigned charchar *)ethernet_protocol->ether_shost;//获取源mac  
  20. printf("Mac Source Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(p_mac_string+0),*(p_mac_string+1),*(p_mac_string+2),*(p_mac_string+3),*(p_mac_string+4),*(p_mac_string+5));  
  21.   
  22. p_mac_string = (unsigned charchar *)ethernet_protocol->ether_dhost;//获取目的mac  
  23. printf("Mac Destination Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(p_mac_string+0),*(p_mac_string+1),*(p_mac_string+2),*(p_mac_string+3),*(p_mac_string+4),*(p_mac_string+5));  


b)

int pcap_loop( pcap_t *p,

int cnt,

pcap_handler callback,

u_char *user )

功能

循环捕获网络数据包,直到遇到错误或者满足退出条件。每次捕获一个数据包就会调用 callback 指定的回调函数,所以,可以在回调函数中进行数据包的处理操作。

参数

ppcap_open_live()返回的 pcap_t 类型的指针

cnt:指定捕获数据包的个数,一旦抓到了 cnt 个数据包,pcap_loop 立即返回。如果是 -1,就会永无休止的捕获,直到出现错误。

callback:回调函数,名字任意,根据需要自行起名。

user:向回调函数中传递的参数。


callback 回调函数的定义

void callback( u_char *userarg, 

const struct pcap_pkthdr * pkthdr, 

const u_char * packet )

userarg:pcap_loop() 的最后一个参数,当收到足够数量的包后 pcap_loop 会调用callback 回调函数,同时将pcap_loop()的user参数传递给它
pkthdr:是收到数据包的 pcap_pkthdr 类型的指针,和 pcap_next() 第二个参数是一样的。
packet :收到的数据包数据

返回值

成功返回0,失败返回负数

实例如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. if( pcap_loop(pcap_handle, -1, ethernet_protocol_callback, NULL) < 0 )  
  2. {  
  3.     perror("pcap_loop");  
  4. }  
  5.   
  6. /*******************************回调函数************************************/  
  7. void ethernet_protocol_callback(unsigned charchar *argument,const struct pcap_pkthdr *packet_heaher,const unsigned charchar *packet_content)  
  8. {  
  9.     unsigned charchar *mac_string;              //  
  10.     struct ether_header *ethernet_protocol;  
  11.     unsigned short ethernet_type;           //以太网类型  
  12.     printf("----------------------------------------------------\n");  
  13.     printf("%s\n", ctime((time_ttime_t *)&(packet_heaher->ts.tv_sec))); //转换时间  
  14.     ethernet_protocol = (struct ether_header *)packet_content;  
  15.       
  16.     mac_string = (unsigned charchar *)ethernet_protocol->ether_shost;//获取源mac地址  
  17.     printf("Mac Source Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(mac_string+0),*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));  
  18.       
  19.     mac_string = (unsigned charchar *)ethernet_protocol->ether_dhost;//获取目的mac  
  20.     printf("Mac Destination Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(mac_string+0),*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));  
  21.       
  22.     ethernet_type = ntohs(ethernet_protocol->ether_type);//获得以太网的类型  
  23.     printf("Ethernet type is :%04x\n",ethernet_type);  
  24.     switch(ethernet_type)  
  25.     {  
  26.         case 0x0800:printf("The network layer is IP protocol\n");break;//ip  
  27.         case 0x0806:printf("The network layer is ARP protocol\n");break;//arp  
  28.         case 0x0835:printf("The network layer is RARP protocol\n");break;//rarp  
  29.         default:break;  
  30.     }  
  31.     usleep(800*1000);  
  32. }  

c)

int pcap_dispatch(pcap_t * p, int cnt, pcap_handler callback, u_char * user)

这个函数和 pcap_loop() 非常类似,只是在超过 to_ms 毫秒后就会返回( to_ms 是pcap_open_live() 的第4个参数 )


5、释放网络接口

void pcap_close(pcap_t *p)

功能

关闭 pcap_open_live() 打开的网络接口(即其返回值,pcap_t 类型指针),并释放相关资源。注意,操作完网络接口,应该释放其资源。

参数

需要关闭的网络接口,pcap_open_live() 的返回值(pcap_t 类型指针

返回值

实例如下:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. // 打开网络接口  
  2. pcap_t * pcap_handle = pcap_open_live("eth0"102410, error_content);  
  3. if(NULL == pcap_handle)  
  4. {  
  5.     printf(error_content);  
  6.     exit(-1);  
  7. }  
  8.   
  9. //// ……  
  10. //// ……  
  11.   
  12. pcap_close(pcap_handle); //释放网络接口  


例子1(接收一个数据包):

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <pcap.h>  
  3. #include <arpa/inet.h>  
  4. #include <time.h>  
  5. #include <stdlib.h>  
  6. struct ether_header  
  7. {  
  8.     unsigned char ether_dhost[6];   //目的mac  
  9.     unsigned char ether_shost[6];   //源mac  
  10.     unsigned short ether_type;      //以太网类型  
  11. };  
  12. #define BUFSIZE 1514  
  13.   
  14. int main(int argc,charchar *argv[])  
  15. {  
  16.     pcap_t * pcap_handle = NULL;  
  17.     char error_content[100] = "";   // 出错信息  
  18.     const unsigned charchar *p_packet_content = NULL;       // 保存接收到的数据包的起始地址  
  19.     unsigned charchar *p_mac_string = NULL;         // 保存mac的地址,临时变量  
  20.     unsigned short ethernet_type = 0;           // 以太网类型  
  21.     charchar *p_net_interface_name = NULL;      // 接口名字  
  22.     struct pcap_pkthdr protocol_header;  
  23.     struct ether_header *ethernet_protocol;  
  24.   
  25.     //获得接口名  
  26.     p_net_interface_name = pcap_lookupdev(error_content);  
  27.     if(NULL == p_net_interface_name)  
  28.     {  
  29.         perror("pcap_lookupdev");  
  30.         exit(-1);  
  31.     }  
  32.       
  33.     //打开网络接口  
  34.     pcap_handle = pcap_open_live(p_net_interface_name,BUFSIZE,1,0,error_content);  
  35.     p_packet_content = pcap_next(pcap_handle,&protocol_header);  
  36.       
  37.     printf("------------------------------------------------------------------------\n");  
  38.     printf("capture a Packet from p_net_interface_name :%s\n",p_net_interface_name);  
  39.     printf("Capture Time is :%s",ctime((const time_ttime_t *)&protocol_header.ts.tv_sec));  
  40.     printf("Packet Lenght is :%d\n",protocol_header.len);  
  41.       
  42.     /* 
  43.     *分析以太网中的 源mac、目的mac 
  44.     */  
  45.     ethernet_protocol = (struct ether_header *)p_packet_content;  
  46.     p_mac_string = (unsigned charchar *)ethernet_protocol->ether_shost;//获取源mac  
  47.     printf("Mac Source Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(p_mac_string+0),*(p_mac_string+1),*(p_mac_string+2),*(p_mac_string+3),*(p_mac_string+4),*(p_mac_string+5));  
  48.     p_mac_string = (unsigned charchar *)ethernet_protocol->ether_dhost;//获取目的mac  
  49.     printf("Mac Destination Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(p_mac_string+0),*(p_mac_string+1),*(p_mac_string+2),*(p_mac_string+3),*(p_mac_string+4),*(p_mac_string+5));  
  50.   
  51.     /* 
  52.     *获得以太网的数据包的地址,然后分析出上层网络协议的类型 
  53.     */  
  54.     ethernet_type = ntohs(ethernet_protocol->ether_type);  
  55.     printf("Ethernet type is :%04x\t",ethernet_type);  
  56.     switch(ethernet_type)  
  57.     {  
  58.         case 0x0800:printf("The network layer is IP protocol\n");break;//ip  
  59.         case 0x0806:printf("The network layer is ARP protocol\n");break;//arp  
  60.         case 0x0835:printf("The network layer is RARP protocol\n");break;//rarp  
  61.         default:printf("The network layer unknow!\n");break;  
  62.     }  
  63.       
  64.     pcap_close(pcap_handle);  
  65.     return 0;  
  66. }  


注意:gcc 编译时需要加上 -lpcap,运行时需要使用超级权限



例子2(接收多个数据包):

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <stdio.h>  
  2. #include <pcap.h>  
  3. #include <arpa/inet.h>  
  4. #include <time.h>  
  5. #include <stdlib.h>  
  6.   
  7. #define BUFSIZE 1514  
  8.   
  9. struct ether_header  
  10. {  
  11.     unsigned char ether_dhost[6];   //目的mac  
  12.     unsigned char ether_shost[6];   //源mac  
  13.     unsigned short ether_type;      //以太网类型  
  14. };  
  15.   
  16. /*******************************回调函数************************************/  
  17. void ethernet_protocol_callback(unsigned charchar *argument,const struct pcap_pkthdr *packet_heaher,const unsigned charchar *packet_content)  
  18. {  
  19.     unsigned charchar *mac_string;              //  
  20.     struct ether_header *ethernet_protocol;  
  21.     unsigned short ethernet_type;           //以太网类型  
  22.     printf("----------------------------------------------------\n");  
  23.     printf("%s\n", ctime((time_ttime_t *)&(packet_heaher->ts.tv_sec))); //转换时间  
  24.     ethernet_protocol = (struct ether_header *)packet_content;  
  25.       
  26.     mac_string = (unsigned charchar *)ethernet_protocol->ether_shost;//获取源mac地址  
  27.     printf("Mac Source Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(mac_string+0),*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));  
  28.     mac_string = (unsigned charchar *)ethernet_protocol->ether_dhost;//获取目的mac  
  29.     printf("Mac Destination Address is %02x:%02x:%02x:%02x:%02x:%02x\n",*(mac_string+0),*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));  
  30.       
  31.     ethernet_type = ntohs(ethernet_protocol->ether_type);//获得以太网的类型  
  32.     printf("Ethernet type is :%04x\n",ethernet_type);  
  33.     switch(ethernet_type)  
  34.     {  
  35.         case 0x0800:printf("The network layer is IP protocol\n");break;//ip  
  36.         case 0x0806:printf("The network layer is ARP protocol\n");break;//arp  
  37.         case 0x0835:printf("The network layer is RARP protocol\n");break;//rarp  
  38.         default:break;  
  39.     }  
  40.     usleep(800*1000);  
  41. }  
  42.   
  43. int main(int argc, charchar *argv[])  
  44. {  
  45.     char error_content[100];    //出错信息  
  46.     pcap_t * pcap_handle;  
  47.     unsigned charchar *mac_string;                
  48.     unsigned short ethernet_type;           //以太网类型  
  49.     charchar *net_interface = NULL;                 //接口名字  
  50.     struct pcap_pkthdr protocol_header;  
  51.     struct ether_header *ethernet_protocol;  
  52.       
  53.     //获取网络接口  
  54.     net_interface = pcap_lookupdev(error_content);  
  55.     if(NULL == net_interface)  
  56.     {  
  57.         perror("pcap_lookupdev");  
  58.         exit(-1);  
  59.     }  
  60.   
  61.     pcap_handle = pcap_open_live(net_interface,BUFSIZE,1,0,error_content);//打开网络接口  
  62.           
  63.     if(pcap_loop(pcap_handle,-1,ethernet_protocol_callback,NULL) < 0)  
  64.     {  
  65.         perror("pcap_loop");  
  66.     }  
  67.       
  68.     pcap_close(pcap_handle);  
  69.     return 0;  
  70. }  


运行情况如下:


过滤数据包

我们抓到的数据包往往很多,如何过滤掉我们不感兴趣的数据包呢?


几乎所有的操作系统( BSD, AIX, Mac OS, Linux 等)都会在内核中提供过滤数据包的方法,主要都是基于 BSD Packet Filter( BPF ) 结构的。libpcap 利用 BPF 来过滤数据包。


1)设置过滤条件
BPF 使用一种类似于汇编语言的语法书写过滤表达式,不过 libpcap 和 tcpdump 都把它封装成更高级且更容易的语法了,具体可以通过 man tcpdump查看:




以下是一些例子:

src host 192.168.1.177
只接收源 ip 地址是 192.168.1.177 的数据包

dst port 80
只接收 tcp/udp 的目的端口是 80 的数据包

not tcp
只接收不使用 tcp 协议的数据包

tcp[13] == 0x02 and (dst port 22 or dst port 23)
只接收 SYN 标志位置位且目标端口是 22 或 23 的数据包( tcp 首部开始的第 13 个字节)

icmp[icmptype] == icmp-echoreply or icmp[icmptype] == icmp-echo
只接收 icmp 的 ping 请求和 ping 响应的数据包

ehter dst 00:e0:09:c1:0e:82
只接收以太网 mac 地址是 00:e0:09:c1:0e:82 的数据包

ip[8] == 5
只接收 ip 的 ttl=5 的数据包(ip首部开始的第8个字节)


2)编译 BPF 过滤规则

int pcap_compile(  pcap_t *p,

struct bpf_program *fp,

char *buf,

int optimize,

bpf_u_int32 mask )

功能

编译 BPF 过滤规则

参数

p:pcap_open_live() 返回的 pcap_t 类型的指针

fp:存放编译后的 bpf,应用过滤规则时需要用到这个指针

buf:过滤条件

optimize:是否需要优化过滤表达式

mask:指定本地网络的网络掩码,不需要时可写 0

返回值

成功返回 0,失败返回 -1


3)应用 BPF 过滤规则

int pcap_setfilter( pcap_t * p,  struct bpf_program * fp )

功能

应用 BPF 过滤规则,简单理解为让过滤生效

参数

p:pcap_open_live() 返回的 pcap_t 类型的指针

fp:pcap_compile() 的第二个参数

返回值:

成功返回 0,失败返回 -1


这个编译应用过程,有点类似于,我们写一个 C 程序,先编译,后运行的过程


应用完过滤表达式之后我们便可以使用 pcap_loop() 或 pcap_next() 等抓包函数来抓包了。


下面的程序演示了如何过滤数据包,我们只接收目的端口是 80 的数据包:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <pcap.h>  
  2. #include <time.h>  
  3. #include <stdlib.h>  
  4. #include <stdio.h>  
  5.   
  6. void getPacket(u_char * arg, const struct pcap_pkthdr * pkthdr, const u_char * packet)  
  7. {  
  8.   intint * id = (intint *)arg;  
  9.     
  10.   printf("id: %d\n", ++(*id));  
  11.   printf("Packet length: %d\n", pkthdr->len);  
  12.   printf("Number of bytes: %d\n", pkthdr->caplen);  
  13.   printf("Recieved time: %s", ctime((const time_ttime_t *)&pkthdr->ts.tv_sec));   
  14.     
  15.   int i;  
  16.   for(i=0; i<pkthdr->len; ++i)  
  17.   {  
  18.     printf(" %02x", packet[i]);  
  19.     if( (i + 1) % 16 == 0 )  
  20.     {  
  21.       printf("\n");  
  22.     }  
  23.   }  
  24.     
  25.   printf("\n\n");  
  26. }  
  27.   
  28. int main()  
  29. {  
  30.   char errBuf[PCAP_ERRBUF_SIZE], * devStr;  
  31.     
  32.   /* get a device */  
  33.   devStr = pcap_lookupdev(errBuf);  
  34.     
  35.   if(devStr)  
  36.   {  
  37.     printf("success: device: %s\n", devStr);  
  38.   }  
  39.   else  
  40.   {  
  41.     printf("error: %s\n", errBuf);  
  42.     exit(1);  
  43.   }  
  44.     
  45.   /* open a device, wait until a packet arrives */  
  46.   pcap_t * device = pcap_open_live(devStr, 6553510, errBuf);  
  47.     
  48.   if(!device)  
  49.   {  
  50.     printf("error: pcap_open_live(): %s\n", errBuf);  
  51.     exit(1);  
  52.   }  
  53.     
  54.   /* construct a filter */  
  55.   struct bpf_program filter;  
  56.   pcap_compile(device, &filter, "dst port 80"10);  
  57.   pcap_setfilter(device, &filter);  
  58.     
  59.   /* wait loop forever */  
  60.   int id = 0;  
  61.   pcap_loop(device, -1, getPacket, (u_char*)&id);  
  62.     
  63.   pcap_close(device);  
  64.   
  65.   return 0;  
  66. }  

源代码下载请点此处。

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 屋里有股石灰味怎么办 厨房太阳对着晒怎么办 房子有太阳西斜怎么办 房子晒到太阳很热怎么办 房子被太阳热了怎么办 房间西晒窗帘不遮光怎么办 新建房屋一面墙体有裂缝怎么办 卫生间地砖缝隙出现渗水怎么办 西户窗户太晒怎么办 西晒的墙面很烫怎么办 儿童房颜色太粉了怎么办? 小孩在家里偷钱怎么办 脾气不好的猫该怎么办 二年孩子偷钱怎么办 孩子偷钱2000报警怎么办? 我儿子十岁老是偷钱怎么办 13孩子偷同学钱怎么办 孩子偷同学的钱怎么办 儿子十四岁了老偷钱怎么办 发现初中生的儿子偷钱怎么办 被亲戚怀疑儿子偷钱怎么办 房门选的太白了怎么办 大厅地砖颜色比墙砖浅怎么办 房屋外墙渗水物业不管怎么办 走丢了怎么办教学反思 托班教案迷路了怎么办 大班安全教案遇到小偷怎么办 小班孩子舞台表演找不到位置怎么办 懂你英语学完了怎么办 小班社会走丢了怎么办 帮小老鼠搬鸡蛋怎么办 小老鼠还能怎么办鸡蛋 中班教案走丢了怎么办 走丢了怎么办可后反思 社会走丢了怎么办教案 孩子一直不吃幼儿园的饭怎么办 大班安全游泳抽筋怎么办反思 汤洒了怎么办教学反思 迷路了怎么办小班详案 大班牙又痛又摇怎么办 大班安全教案着火了怎么办