1综合实训报告题目:网络流量在线分析系统的设计与实现2信息学院计算机科学系目录一、实训目的………………………………………………3二、实训内容………………………………………………3三、主要设备及环境………………………………………3四、设计与步骤……………………………………………4五、过程与调试……………………………………………22六、整理与小结……………………………………………23七、参考文献………………………………………………24八、附录……………………………………………………253一、实训目的设计并实现一个网络流量的分析系统。该系统具有以下功能:(1)实时抓取网络数据。(2)网络协议分析与显示。(3)将网络数据包聚合成数据流,以源IP、目的IP、源端口、目的端口及协议等五元组的形式存储。(4)计算并显示固定时间间隔内网络连接(双向流)的统计量(如上行与下行的数据包数目,上行与下行的数据量大小等)。在这些统计数据的基础上分析不同网络应用的流量特征。二、实训内容(1)能够实时抓取网络中的数据包。并实时显示在程序界面上。用户可自定义过滤条件以抓取所需要的数据包。(2)分析各个网络协议格式,能够显示各协议字段的实际意义。例如,能够通过该程序反映TCP三次握手的实现过程。(3)采用Hash链表的形式将网络数据以连接(双向流)的形式存储。(4)计算并显示固定时间间隔内网络连接(双向流)的统计量(如上行与下行的数据包数目,上行与下行的数据量大小等)。例如,抓取一段时间(如30分钟)的网络流量,将该段时间以固定时长(如1分钟)为单位分成若干个时间片,计算网络连接在每一个时间片内的相关统计量。并在上述统计数据的基础上分析不同应用如WEB、DNS、在线视频等服务的流量特征。注意,可根据实际的流量分析需要自己定义相关的统计量。三、主要设备及环境硬件设备:(1)台式计算机或笔记本计算机(含网络适配器)软件设备:(2)Windows操作系统4(3)网络数据包捕获函数包,Windows平台为winpcap(4)编程语言选用C/C++。(5)编程环境为codeblocks四、设计与步骤(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);5实验结果显示如下:(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地址*/{6printf(\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地址转换为点格式*/#defineIPTOSBUFFERS12char*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];}7结果显示如下:(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);8if(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;/*@#$%^&*!*/elsenetmask=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)0){printf(Error\n);pcap_freealldevs(alldevs);exit(-1);9}结果显示如下:(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_time0)?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);}结果显示如下:10(7)抓包时调用函数pcap_loop()函数调用cb_getPacket()函数,实现在线程内的抓包,Sleep函数一旦结束,通过pcap_breakloop()退出抓包:pcap_loop(cap_ins_