网络流量在线分析系统的设计与实现.docx 您所在的位置:网站首页 pcap_createsrcstr 网络流量在线分析系统的设计与实现.docx

网络流量在线分析系统的设计与实现.docx

2023-04-15 20:59| 来源: 网络整理| 查看: 265

网络流量在线分析系统的设计与实现.docx

网络流量在线分析系统的设计与实现.docx

文档编号:1915296上传时间:2023-03-30格式:DOCX页数:41大小:105.70KB

综合实训

报告

题目:

网络流量在线分析系统的设计与实现

22

信息学院计算机科学系目 录

一、

实训目的………………………………………………

3

二、

实训内容………………………………………………

3

三、

主要设备及环境………………………………………

3

四、

设计与步骤……………………………………………

4

五、

过程与调试……………………………………………

22

六、

整理与小结……………………………………………

23

七、

参考文献………………………………………………

24

八、

附录……………………………………………………

25

一、实训目的

设计并实现一个网络流量的分析系统。

该系统具有以下功能:

(1)实时抓取网络数据。

(2)网络协议分析与显示。

(3)将网络数据包聚合成数据流,以源IP、目的IP、源端口、目的端口及协议等五元组的形式存储。

(4)计算并显示固定时间间隔内网络连接(双向流)的统计量(如上行与下行的数据包数目,上行与下行的数据量大小等)。

在这些统计数据的基础上分析不同网络应用的流量特征。

二、实训内容

(1)能够实时抓取网络中的数据包。

并实时显示在程序界面上。

用户可自定义过滤条件以抓取所需要的数据包。

(2)分析各个网络协议格式,能够显示各协议字段的实际意义。

例如,能够通过该程序反映TCP三次握手的实现过程。

(3)采用Hash链表的形式将网络数据以连接(双向流)的形式存储。

(4)计算并显示固定时间间隔内网络连接(双向流)的统计量(如上行与下行的数据包数目,上行与下行的数据量大小等)。

例如,抓取一段时间(如

30分钟)的网络流量,将该段时间以固定时长(如1分钟)为单位分成若干个时间片,计算网络连接在每一个时间片内的相关统计量。

并在上述统计数据的基础上分析不同应用如WEB、DNS、在线视频等服务的流量特征。

注意,可根据

实际的流量分析需要自己定义相关的统计量。

三、主要设备及环境

硬件设备:

(1)台式计算机或笔记本计算机(含网络适配器)软件设备:

(2)Windows操作系统

(3)网络数据包捕获函数包,Windows平台为winpcap

(4)编程语言选用C/C++。

(5)编程环境为codeblocks

4、设计与步骤

(1)设计代码检索机器所连接的所有网络适配器,并在屏幕中显示适配器的名称和详细信息,用户可以输入适配器编号选择指定的适配器用来捕获包,如果没有找到适配器,提示用户检查WinPcap是否安装,代码与结果显示如下:

/*setthesource*/

if(pcap_createsrcstr(source,PCAP_SRC_IFLOCAL,NULL,NULL,NULL,errbuf)==-1){

printf("%s\n",errbuf);exit(-1);

}

printf("source:

%s",source);

/*findalldevices*/

if(pcap_findalldevs_ex(source,NULL,&alldevs,errbuf)==

-1){

printf("%s\n",errbuf);exit(-1);

}

/*chooseonedevices*/d=alldevs;

while(d!

=NULL){

printf("%s,%s\n",d->name,d->description);d=d->next;

}

printf("chooseadevice[numberbetween1to4]:

");scanf("%d",&i);

d=alldevs;while(--i)

d=d->next;

printf("\n---------------------------------------------

-\n");

printf("selecteddevice:

%s\n",d->name);

实验结果显示如下:

(2)选择指定适配器后,调用ifprint();函数计算本机的IP地址、掩码、广播地址、目标地址等信息,并用声明staticcharb;用来记录本机IP地址,为接下来查找Hash表判断流量包的流向做准备:

voidifprint(pcap_if_t*d)

{

pcap_addr_t*a;

/*名称*/

//printf("%s\n",d->name);

/*描述*/

if(d->description)

printf("\tDescription:

%s\n",d->description);

/*回环地址*/

printf("\tLoopback:

%s\n",(d->flags&PCAP_IF_LOOPBACK)?

"yes":

"no");

/*IP地址*/

for(a=d->addresses;a;a=a->next)

{

printf("\tAddressFamily:

#%d\n",a->addr->sa_family);

switch(a->addr->sa_family)

{

caseAF_INET:

printf("\tAddressFamilyName:

AF_INET\n");

if(a->addr)

/*Y-IP地址*/

{

printf("\tAddress:

%s\n",iptos(((structsockaddr_in*)a-

>addr)->sin_addr.s_addr));

b=iptos(((structsockaddr_in*)a->addr)-

>sin_addr.s_addr);

}

if(a->netmask)

/*Y-掩码*/

printf("\tNetmask:

%s\n",iptos(((structsockaddr_in

*)a->netmask)->sin_addr.s_addr));

if(a->broadaddr)

/*Y-广播地址*/

printf("\tBroadcastAddress:

%s\n",iptos(((structsockaddr_in*)a->broadaddr)->sin_addr.s_addr));

if(a->dstaddr)

/*Y-目标地址*/

printf("\tDestinationAddress:

%s\n",iptos(((structsockaddr_in*)a->dstaddr)->sin_addr.s_addr));

break;

default:

/*未知*/

printf("\tAddressFamilyName:

Unknown\n");

break;

}

}

printf("\n");

}

/*来自tcptracert,把数字IP地址转换为点格式*/#defineIPTOSBUFFERS12

char*iptos(u_longin)

{

staticcharoutput[IPTOSBUFFERS][3*4+3+1];

staticshortwhich;

u_char*p;

p=(u_char*)∈

which=(which+1==IPTOSBUFFERS?

0:

which+1);

sprintf(output[which],"%d.%d.%d.%d",p[0],p[1],p[2],p[3]);

returnoutput[which];

}

结果显示如下:

(3)接收到用户输入的适配器编号,打开指定适配器:

/*openonedevice*/

cap_ins_des=pcap_open(d->name,65536,PCAP_OPENFLAG_PROMISCUOUS,1000,NULL,errbuf);

if(cap_ins_des==NULL){printf("%s\n",errbuf);pcap_freealldevs(alldevs);exit(-1);

}

(4)打开指定文件存储捕获的数据包:

/*openafiletodumpdata*/

dumpfp=pcap_dump_open(cap_ins_des,"traffic1");if(dumpfp==NULL){

printf("Erroronopeningoutputfile\n");exit(-1);

}

(5)在main()函数开始做一个声明,方便用户自由选择过滤规则,声明如下:

intswitchnum;

chart1[]="ip";//ip过滤规则

chart2[]="ipandtcp";//tcp过滤规则

chart3[]="ipandudp";//udp过滤规则

chart4[]="";//mac帧过滤

charpacket_filter[100];//thefilter

设置过滤规则时使用swich()语句判断用户输入的编号,是对应的编号与对应的过滤规则相一致:

/*openafiletodumpdata*/

dumpfp=pcap_dump_open(cap_ins_des,"traffic1");if(dumpfp==NULL){

printf("Erroronopeningoutputfile\n");exit(-1);

}

/*getthenetmask,usedatcompilingthefilter*/if(d->addresses!

=NULL)

netmask=((structsockaddr_in*)(d->addresses-

>netmask))->sin_addr.S_un.S_addr; /*@#$%^&*!

*/else

netmask=0xffffff; /*255.25.255.0*/

//netmask=0;

/*选择过滤规则*/

printf("\n \n");

printf("%d:

%s\n",1,"IP协议");

printf("%d:

%s\n",2,"IP和TCP协议");

printf("%d:

%s\n",3,"IP和UDP协议");

printf("%d:

%s\n",4,"MAC帧");

printf("请选择要获取的协议类型):

");

scanf("%d",&switchnum);

switch(switchnum){

case1:

strcpy(packet_filter,t1);

break;

case2:

strcpy(packet_filter,t2);

break;

case3:

strcpy(packet_filter,t3);

break;

case4:

strcpy(packet_filter,t4);

break;

default:

printf("error\n");

}

/*compilethefilter*/

if(pcap_compile(cap_ins_des,&fcode,packet_filter,1,netmask)

printf("Error\n");pcap_freealldevs(alldevs);exit(-1);

}

结果显示如下:

(6)用户可以根据提示设置抓包的时间长短,该功能的实现依靠创建一个线程:

pthread_tptClock;

argumentargs;

args.handle=cap_ins_des;

intargv_time=atoi(argv[1]);

inttimeLen;

printf("\n设置抓包时长:

");

scanf("%d",&timeLen);

printf("设置抓包时长为%ds",timeLen);

args.timeLen=(argv_time>0)?

argv_time:

timeLen;

//intargv_time=2;

//args.timeLen=argv_time;

//printf("抓取时长:

%ds\n",args.timeLen);

if(pthread_create(&ptClock,NULL,thread_clock,&args))

{

printf("pthread_create():

Error!

\n");

return-1;

}

void*thread_clock(void*argv)

{

pcap_t*handle=((argument*)argv)->handle;

inttimeLen=((argument*)argv)->timeLen;//settime

//printf("%d",timeLen);

Sleep(timeLen*1000);

pcap_breakloop(handle);

}

结果显示如下:

(7)抓包时调用函数pcap_loop()函数调用cb_getPacket()函数,实现在线程内的抓包,Sleep函数一旦结束,通过pcap_breakloop()退出抓包:

pcap_loop(cap_ins_des,-1,cb_getPacket,(u_char*)dumpfp);

voidcb_getPacket(u_char*dumpfile,conststructpcap_pkthdr*pkthdr,constu_char*packet)

{

//ip_header*seg_ip=(ip_header*)(package+ETHER_LEN);

pcap_dump(dumpfile,pkthdr,packet);

ethernet_protocol_packet_callback(dumpfile,pkthdr,packet);

}

(8)设置完成抓包时长后,系统开始进行抓包,一旦抓包结束,调用

pcap_close()关闭会话并释放适配器列表:

pcap_close(cap_ins_des);

pcap_freealldevs(allAdapters);//释放适配器列表

(9)捕获结束后将捕获的数据包存入traffic1.data文件中,再将文件打开进行分析,打开文件之前使用pcap_createsrcstr函数指明文件位置为本机文件,文件名为“traffic1.data”,在调用pcap_open()打开捕

获文件:

pcap_t*fp;//文件指针

//pcap_createsrcstr指明打开文件的地方:

本地文件

if(pcap_createsrcstr(source,/*源字符串*/

PCAP_SRC_FILE,/*本机文件*/

NULL,/*远程主机*/

NULL,/*远程主机端口*/

"traffic1",/*文件名*/

errbuf/*错误缓冲区*/)!

=0)

{

fprintf(stderr,"\nErrorincreatesourcestring:

%s\n",errbuf);

return-1;

}

//打开捕获文件

if((fp=pcap_open(source,/*设备名*/65536,/*要捕捉的数据包的部分,65535保证能捕获到不同数据链路层上的每个数据包的全部内容*/

PCAP_OPENFLAG_PROMISCUOUS,//混杂模式1000,//读取超时时间

NULL,//远程机器验证errbuf//错误缓冲池

))==NULL)

{

fprintf(stderr,"\nCannotopenthefile%s.\n",

source);

return-1;

}

(10)打开文件开始对数据包进行分析,通过timeval记录当前时间和上一次采样时间,通过计算可以求出延迟时间,根据数据包的大小,进行字节转换,求出采样时每秒的比特数以及每秒的数据包数量:

structtimeval*old_ts=(structtimeval*)argument;

u_intdelay;

LARGE_INTEGERBps,Pps;

structtm*ltime;

chartimestr[16];

time_tlocal_tv_sec;

//以毫秒计算上一次采样的延迟时间

//这个值通过采样到的时间戳获得

delay=(packet_header->ts.tv_sec-old_ts->tv_sec)*1000000-old_ts->tv_usec+packet_header->ts.tv_usec;

//获取每秒的比特数b/s

//Bps.QuadPart=(((*(LONGLONG*)(packet_content+8))*8

*1000000)/(delay));

/*^^

||

||

||

将字节转换成比特--||

延时是以毫秒表示的--|

*/

u_intm=(*(LONGLONG*)(packet_content+8))*8*1000000;

u_intn=((*(LONGLONG*)(packet_content))*1000000);

Bps.QuadPart=m/delay;

Pps.QuadPart=n/delay;

//printf("%I64u\n",m);

//printf("%I64u\n",delay);

//得到每秒的数据包数量

//Pps.QuadPart=(((*(LONGLONG*)(packet_content))*1000000)/(delay));

//将时间戳转化为可识别的格式

/*local_tv_sec=packet_header->ts.tv_sec;

ltime=localtime(&local_tv_sec);

strftime(timestr,sizeoftimestr,"%H:

%M:

%S",ltime);*/

//打印时间戳

//printf("%s",timestr);

//打印采样结果

//printf("%I64u\n",delay);

printf("\n**************************************************\n每秒的比特数:

");

printf("BPS=%I64u\n",Bps.QuadPart);

printf("每秒的数据包数量:

");

printf("PPS=%I64u\n",Pps.QuadPart);

//存储当前的时间戳

old_ts->tv_sec=packet_header->ts.tv_sec;

old_ts->tv_usec=packet_header->ts.tv_usec;

结果显示如下:

(11)通过捕获的文件,对抓取的每个数据包的各层的首部进行解析,并将解析结果进行显示

①首先对以太网协议进行解析:

printf("捕获第%d个网络数据包\n",packet_number);

printf("捕获时间:

");

printf("%s",ctime((consttime_t*)&packet_header-

>ts.tv_sec));

printf("数据包长度:

");

printf("%d\n",packet_header->len);

printf("\n--------------以太网协议 \n");

eth



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有