最近老师让写一个流量监控程序,用到了libpcap编程。虽然很简单,但是前期也走了一些弯路。最初是直接从别人博客里面copy的代码,然后运行时就是结果就是不正确。本以为是系统问题,我又装了个双系统。。。

现在我把自己的代码分享出来吧,这些是我自己运行成功的,代码很简单,只是希望能给新人一些借鉴。

首先:我们先得到我们的设备名称,因为之后我们需要根据名称指针来打开我们的设备,得到名称指针的方式如下:

/*get our device name*/

char *dev,errbuf[PCAP_ERRBUF_SIZE];

dev = pcap_lookupdev(errbuf);

printf("Device: %s\n",dev); /*print our device name*/

如果我们实现已经知道设备名称了,就不用在通过这个方式得到了。

得到名称之后,我们根据名称指针打开我们的设备,这时候我们需要用到的函数是:

/*pcap_t *pcap_open_dev(char*device,int snaplen,int promisc,int to_ms,char*errbuf);*/

device是设备名称,snaplen是pcap将捕获的最大字节数,promisc是混合模式,to_ms是读取时的超时值,单位是毫秒,为0则一直嗅探直到错误发生,errbuf是出错之后信息的储存。

函数的返回值是一个句柄,在下面我们将会使用的到。

/*open device and sniff

*pcap_t *pcap_open_dev(char*device,int snaplen,int promisc,int to_ms,char*errbuf);

*

*/

pcap_t * open_dev = pcap_open_live(dev,65535,1,0,errbuf);

if(!open_dev){

printf("open device failed: %s",errbuf);

}

打开设备之后,我们设置过滤条件,过滤掉我们不想要的包。设置过滤涉及到两个函数:

int pcap_compile(pcap_t *p,struct bpf_program *fp,char *str,int optimize,bpf_u_int32 netmask)

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

pcap_compile的第一个参数就是刚刚我们打开设备的返回值,后面是我们存储被编译的过滤器版本的地址的引用。

str是我们的过滤条件。比如"tcp port 21"是指只抓取来自tcp协议,并且端口是21的包。optimize是一个定义表达式是否被优化的整形量,netmask是表示网络掩码。

pcap_setfilter则是用的都是pcap_compile里面已经出现过的函数。

好,现在我们开始设置过滤:

struct bpf_program filter;

char filter_exp[] = "port 80";/*filter expressiong*/

bpf_u_int32 mask; /*net mask*/

pcap_compile(open_dev,&filter,filter_exp,0,mask);

pcap_setfilter(open_dev,&filter);

接下来我们就开始循环捕获了,在这里我用到的函数是pcap_loop,下面是它的函数原型:

int pcap_loop(pcap_t *p,int cnt,pcap_hander callback,u_char *user)

其中:pcap_t还是我们的句柄,cnt是表示我们想要捕获多少个数据包,如果值为-1,则表示一直捕获,直到出错位置。pcap_hander则是我们回调函数的名称,user是我们想发送给回调函数的参数,如果没有,那么设置成NULL;

pthread_attr_init(&attr);

pthread_create(&tid,&attr,runner,NULL);//这两句是创建线程用的,为了每秒都显示流量情况。

pcap_loop(open_dev,-1,got_packet,NULL);

pcap_close(open_dev);

got_packet()是用户自定义的函数,可以根据自己的需要定义。下面是我定义的:

void got_packet(u_char *argv,const struct pcap_pkthdr *header,const u_char *packet){

int len2 = (int)header->caplen;

Ethernet *ethernet = (Ethernet *)(packet);

Ip_header *ip = (Ip_header *)(packet + sizeof(Ethernet));

if(ip->proto==(u_char)6){ //6是tcp协议

tcp_count += len2;

}else if(ip->proto == (u_char)17){ //17是代表使用的udp协议

udp_count += len2;

}

count +=len2; //count是为了统计总流量写的,在函数外面声明的,同理udp_count,tcp_count

}

Ethernet ,Ip_header是定义的结构体,这是为了进一步解析抓到的数据包用的。下面是结构体原型。(其中有些是直接网上copy的)

/* *以太网帧的首部 */

typedef struct ethernet{

u_char host1[6];

u_char host2[6];

u_short type;

}Ethernet;

/* IPv4 首部 */

typedef struct ip_header{

u_char ver_ihl; // 版本 (4 bits) + 首部长度 (4 bits)

u_char tos; // 服务类型(Type of service)

u_short tlen; // 总长(Total length)

u_short identification; // 标识(Identification)

u_short flags_fo; // 标志位(Flags) (3 bits) + 段偏移量(Fragment offset) (13 bits)

u_char ttl; // 存活时间(Time to live)

u_char proto; // 协议(Protocol)

u_short crc; // 首部校验和(Header checksum)

int saddr; // 源地址(Source address)

int daddr; // 目的地址(Destination address)

}Ip_header;

当然,如果你想解析到更多的数据,那么你可能还需要另tcp_heaer,和udp_header。如下:

/* UDP 首部*/

typedef struct udp_header{

u_short sport; // 源端口(Source port)

u_short dport; // 目的端口(Destination port)

u_short len; // UDP数据包长度(Datagram length),the minimum is 8

u_short crc; // 校验和(Checksum)

}Udp_header;

/*TCP首部*/

typedef struct tcp_header{

u_short sport;//源端口

u_short dPort;//目的端口

unsigned int SequNum;//序号

unsigned int AckNum;//确认号

u_short sHeaderLenAndFlag;//数据偏移+保留+URG+ACK+RST+SYN+FIN

u_short WinSize;//窗口大小

u_short CheckSum;//检验和

u_short urgentPointer;//紧急指针

}Tcp_header;

这里面的代码是流量监控的大部分,完整的代码附件可以在这里下载,不需要积分。

http://download.csdn.net/detail/qq_27856623/9713803

编译的时候需要

gcc my.c -lpcap -lpthread

运行的时候需要sudo ./a.out

linux c libpcap统计流量,libpcap流量统计相关推荐

  1. Linux中一行命令查看网卡流量、统计网络流量的各种实现方法

    Linux中一行命令查看网卡流量.统计网络流量的各种实现方法. 方法一.nload工具 源码包路径: wget http://heanet.dl.sourceforge.net/project/nlo ...

  2. 演示:使用Sniffer统计与分析流量

    演示:使用Sniffer统计与分析流量 Sniffer是统计与分析网络数据流量的一个很好的选择.因为Sniffer的"混杂"模式会接收到同一个物理网络内的所有数据帧,无论是广播帧还 ...

  3. Scala初级实践——统计手机耗费流量(1)

    Scala初级实践--统计手机耗费流量(1) [实验描述] 本实验主要使用Scala语言来实现对手机流量的计算.在该实验中,共有四个需求: 1)统计每一个手机号耗费的总上行流量.下行流量.总流量 2) ...

  4. 统计每一个用户(手机号)所耗费的上行流量,下行流量,总流量

    假设从数据运营商可以获取用户(通过手机号来区分)的上网信息: 1363157985066 13726230503 00-FD-07-A4-72-B8:CMCC 120.196.100.82 i02.c ...

  5. 流量多少 程序统计(已发电脑报)

    目标手机软件 流量多少 程序统计 模仿功能:流量统计 模仿对象:手机QQ 2008 模仿进度:第二期 开发平台:Java平台 3G来了,可移动.联通收费还是按流量计算,像手机QQ 2008这种需要网络 ...

  6. android 流量统计换算,什么是流量?如何计算流量?流量的单位如何换算

    什么是流量?如何计算流量?流量的单位如何换算 上网流量通常用"位"(bit),"字节"(Byte),KB,MB,GB,TB等来表示.它是计算机信息技术用于计量存 ...

  7. linux查看某个端口的流量_linux流量查看工具汇总

    时时了解服务器的流量占用情况,是运维人员要掌握的一个入门技能.不过查看流量的情况的手段很多,工具也很多.如ifconfig脚本实现法.cacti.pnp4nagios.mrtg绘图查看以及iptraf ...

  8. 局域网网络流量监控_【干货】Linux网络安全运维:网络流量监控与分析工具Ntop和Ntopng...

    本文授权转载自微信公众号:计算机与网络安全,转载请联系授权.对于单台服务器网络故障的排查,iftop工具可以轻松实现,但是在监控一个庞大的服务器网络,并且要分析每台主机以及端口的网络状态时,iftop ...

  9. Linux下使用Iptraf进行网络流量的分析

    Linux下使用Iptraf进行网络流量的分析 Posted on 2011/06/15 下面的教程我个人安装的时候,总是失败,在/usr/local/bin目录里没有iptraf这个文件,没有办法直 ...

  10. Linux脚本实战之检测网卡流量

    Linux脚本实战之检测网卡流量 一.脚本要求 二.脚本内容 三.运行脚本 一.脚本要求 1.检测网卡流量,并按规定格式记录在日志中,输出到/data/net.log/目录中以执行脚本时间命令的文件中 ...

最新文章

  1. YARN集群维护部分问题汇总
  2. JAVA SE学习day_03:包装类、文件操作——file
  3. VTK修炼之道30:图像重采样_降采样和升采样技术
  4. 圆桌对话:数字化升级,视频通信云赋能全行业
  5. c语言对中文字符串编码_Python || 学习笔记(1):数据类型字符串变量和编码
  6. Css fade()函数降低颜色变量透明度
  7. python在线包安装mysql_python安装mysql的依赖包mysql-python操作
  8. 线程安全的map_面试必问-几种线程安全的Map解析
  9. BZOJ——1614: [Usaco2007 Jan]Telephone Lines架设电话线
  10. 直接存储器存取(Direct Memory Access,DMA)详细讲解
  11. 为什么你的网站没流量?做不大!让我来告诉你。
  12. struts2中文乱码问题
  13. mac 下 hadoop、spark 的安装及配置
  14. 【机器学习】选择模型
  15. 安装SQL Server 2000 出现挂起文件,需要重启该如何解决?
  16. 项目管理学习总结(11)——项目管理怎么做
  17. UitableView 动态高度的优化 提高寻星效率
  18. php 微信授权 跨域,微信公众号支付 请求跳转code跨域
  19. freeswitch通过limit限制cps
  20. hello yocto

热门文章

  1. 全新BMS开发板 /凌力尔特LTC6804/6811开发板BMS电池管理评估板/储能BMS采集板
  2. 利用jquery的ajax实现文件上传
  3. 校招秋招,网申和测评阶段需要注意的问题
  4. WebRTC,P2P技术,IPv6的一些思考
  5. C++ 小游戏 视频及资料集(八)
  6. 给 Spring boot 项目加缓存
  7. matlab霍夫变换检测直线原理,霍夫变换(霍夫变换检测直线原理)
  8. eclipse插件开发示例
  9. 如何做好一个程序员——摘自水木清华BBS
  10. 智能手机背后隐藏的第二系统 -- OSE