计算机网络课程设计编程实现简单的TCP协议分析器.docx
- 文档编号:12610711
- 上传时间:2023-04-20
- 格式:DOCX
- 页数:19
- 大小:192.53KB
计算机网络课程设计编程实现简单的TCP协议分析器.docx
《计算机网络课程设计编程实现简单的TCP协议分析器.docx》由会员分享,可在线阅读,更多相关《计算机网络课程设计编程实现简单的TCP协议分析器.docx(19页珍藏版)》请在冰豆网上搜索。
计算机网络课程设计编程实现简单的TCP协议分析器
编程实现简单的TCP协议分析器
一、问题描述
编程实现简单的TCP协议分析器,TCP协议分析器是一种用于监督和跟踪网络活动的诊断工具,它从局域网中抓取IP数据包,并对它进行分析得到相应的头部信息,过滤TCP包进行分析,得到TCP包的相应信息。
二、基本要求
1.利用原始套接字实现简单的TCP协议分析器。
2.系统功能包括:
2.1原始套接字与网卡绑定,并接收流经网卡的所有数据包;
2.2对数据包进行分析以获得源IP地址和目的IP地址;
2.3对TCPSegment进行分析以获得其首部详细信息;
2.4显示分析结果。
3建议使用VC++。
三、设计思想
TCP协议的数据传送程序是由二个子程序组成的。
也可以看成是服务器端程序和客户端程序,其中:
服务器端程序的功能是侦听端口号,接收远程主要的TCP连接申请,并接收远程主机传送来的文字数据。
另外一个子程序,也就是所谓的客户端程序,主要实现向网络的远程主机提出TCP连接申请。
程序利用原始套接字抓取局域网中的IP包。
TCP协议分析器实现了sniffer的一部分功能。
而sniffer的工作原理是:
1.把网卡置于混杂模式;2.捕获数据包;3.分析数据包。
RawSocket:
原始套接字可以用它来发送和接收IP层以上的原始数据包,如ICMP,TCP,UDP等。
四、系统结构
(1)Pcap_addr描述网络接口地址;
(2)pcap_pkthdr用来描述每个捕获到的数据包的基本信息;
(3)int_pcaplookupnet获取网络地址和网络掩码;
(4)int_pcaploop循环捕获网络数据包,直到遇到错误或满足退出条件;
(5)pcap_t*pcap_open_dead构造一个libpcap句柄。
五、程序流程(或模块划分)
六、源程序
#include"pcap.h"
structether_header
{
u_int8_tether_dhost[6];
/*目的以太网地址*/
u_int8_tether_shost[6];
/*源以太网地址*/
u_int16_tether_type;
/*以太网类型*/
};
structarp_header
{
u_int16_tarp_hardware_type;
/*硬件类型*/
u_int16_tarp_protocol_type;
/*协议类型*/
u_int8_tarp_hardware_length;
/*硬件地址长度*/
u_int8_tarp_protocol_length;
/*协议地址长度*/
u_int16_tarp_operation_code;
/*操作码*/
u_int8_tarp_source_ethernet_address[6];
/*源以太网地址*/
u_int8_tarp_source_ip_address[4];
/*源IP地址*/
u_int8_tarp_destination_ethernet_address[6];
/*目的以太网地址*/
u_int8_tarp_destination_ip_address[4];
/*目的IP地址*/
};
structip_header
{
#ifdefined(WORDS_BIGENDIAN)
u_int8_tip_version:
4,
/*版本*/
ip_header_length:
4;
/*首部长度*/
#else
u_int8_tip_header_length:
4,ip_version:
4;
#endif
u_int8_tip_tos;
/*服务质量*/
u_int16_tip_length;
/*长度*/
u_int16_tip_id;
/*标识*/
u_int16_tip_off;
/*偏移*/
u_int8_tip_ttl;
/*生存时间*/
u_int8_tip_protocol;
/*协议类型*/
u_int16_tip_checksum;
/*校验和*/
structin_addrip_souce_address;
/*源IP地址*/
structin_addrip_destination_address;
/*目的IP地址*/
};
structudp_header
{
u_int16_tudp_source_port;
/*源端口号*/
u_int16_tudp_destination_port;
/*目的端口号*/
u_int16_tudp_length;
/*长度*/
u_int16_tudp_checksum;
/*校验和*/
};
structtcp_header
{
u_int16_ttcp_source_port;
/*源端口号*/
u_int16_ttcp_destination_port;
/*目的端口号*/
u_int32_ttcp_sequence_liuzhen;
/*序列号*/
u_int32_ttcp_acknowledgement;
/*确认序列号*/
#ifdefWORDS_BIGENDIAN
u_int8_ttcp_offset:
4,
/*偏移*/
tcp_reserved:
4;
/*未用*/
#else
u_int8_ttcp_reserved:
4,
/*未用*/
tcp_offset:
4;
/*偏移*/
#endif
u_int8_ttcp_flags;
/*标记*/
u_int16_ttcp_windows;
/*窗口大小*/
u_int16_ttcp_checksum;
/*校验和*/
u_int16_ttcp_urgent_pointer;
/*紧急指针*/
};
structicmp_header
{
u_int8_ticmp_type;
/*ICMP类型*/
u_int8_ticmp_code;
/*ICMP代码*/
u_int16_ticmp_checksum;
/*校验和*/
u_int16_ticmp_id;
/*标识符*/
u_int16_ticmp_sequence;
/*序列码*/
};
voidtcp_protocol_packet_callback(u_char*argument,conststructpcap_pkthdr*packet_header,constu_char*packet_content)
{
structtcp_header*tcp_protocol;
/*TCP协议变量*/
u_charflags;
/*标记*/
intheader_length;
/*长度*/
u_shortsource_port;
/*源端口*/
u_shortdestination_port;
/*目的端口*/
u_shortwindows;
/*窗口大小*/
u_shorturgent_pointer;
/*紧急指针*/
u_intsequence;
/*序列号*/
u_intacknowledgement;
/*确认号*/
u_int16_tchecksum;
/*校验和*/
tcp_protocol=(structtcp_header*)(packet_content+14+20);
/*获得TCP协议内容*/
source_port=ntohs(tcp_protocol->tcp_source_port);
/*获得源端口*/
destination_port=ntohs(tcp_protocol->tcp_destination_port);
/*获得目的端口*/
header_length=tcp_protocol->tcp_offset*4;
/*长度*/
sequence=ntohl(tcp_protocol->tcp_sequence_liuzhen);
/*序列码*/
acknowledgement=ntohl(tcp_protocol->tcp_acknowledgement);
/*确认序列码*/
windows=ntohs(tcp_protocol->tcp_windows);
/*窗口大小*/
urgent_pointer=ntohs(tcp_protocol->tcp_urgent_pointer);
/*紧急指针*/
flags=tcp_protocol->tcp_flags;
/*标识*/
checksum=ntohs(tcp_protocol->tcp_checksum);
/*校验和*/
printf("-------TCP协议-------\n");
printf("源端口号:
%d\n",source_port);
printf("目的端口号:
%d\n",destination_port);
switch(destination_port)
{
case80:
printf("上层协议为HTTP协议\n");
break;
case21:
printf("上层协议为FTP协议\n");
break;
case23:
printf("上层协议为TELNET协议\n");
break;
case25:
printf("上层协议为SMTP协议\n");
break;
case110:
printf("上层协议POP3协议\n");
break;
default:
break;
}
printf("序列码:
%u\n",sequence);
printf("确认号:
%u\n",acknowledgement);
printf("首部长度:
%d\n",header_length);
printf("保留:
%d\n",tcp_protocol->tcp_reserved);
printf("标记:
");
if(flags&0x08)
printf("PSH");
if(flags&0x10)
printf("ACK");
if(flags&0x02)
printf("SYN");
if(flags&0x20)
printf("URG");
if(flags&0x01)
printf("FIN");
if(flags&0x04)
printf("RST");
printf("\n");
printf("窗口大小:
%d\n",windows);
printf("校验和:
%d\n",checksum);
printf("紧急指针:
%d\n",urgent_pointer);
}
voidip_protocol_packet_callback(u_char*argument,conststructpcap_pkthdr*packet_header,constu_char*packet_content)
{
structip_header*ip_protocol;
/*IP协议变量*/
u_intheader_length;
/*长度*/
u_intoffset;
/*偏移*/
u_chartos;
/*服务质量*/
u_int16_tchecksum;
/*校验和*/
ip_protocol=(structip_header*)(packet_content+14);
/*获得IP协议内容*/
checksum=ntohs(ip_protocol->ip_checksum);
/*获得校验和*/
header_length=ip_protocol->ip_header_length*4;
/*获得长度*/
tos=ip_protocol->ip_tos;
/*获得服务质量*/
offset=ntohs(ip_protocol->ip_off);
/*获得偏移*/
if(ip_protocol->ip_protocol==6)
{
printf("-----------IP协议-----------\n");
printf("版本号:
%d\n",ip_protocol->ip_version);
printf("首部长度:
%d\n",header_length);
printf("服务质量:
%d\n",tos);
printf("总长度:
%d\n",ntohs(ip_protocol->ip_length));
printf("标识:
%d\n",ntohs(ip_protocol->ip_id));
printf("偏移:
%d\n",(offset&0x1fff)*8);
printf("生存时间:
%d\n",ip_protocol->ip_ttl);
printf("协议类型:
%d\n",ip_protocol->ip_protocol);
printf("上层协议为TCP协议\n");
printf("校验和:
%d\n",checksum);
printf("源IP地址:
%s\n",inet_ntoa(ip_protocol->ip_souce_address));
/*获得源IP地址*/
printf("目的IP地址:
%s\n",inet_ntoa(ip_protocol->ip_destination_address));
/*获得目的IP地址*/
}
}
voidethernet_protocol_packet_callback(u_char*argument,conststructpcap_pkthdr*packet_header,constu_char*packet_content)
{
staticintpacket_number=1;
/*数据包个数,静态变量*/
u_shortethernet_type;
/*以太网类型*/
structether_header*ethernet_protocol;
structip_header*ip_protocol;
/*IP协议变量*/
u_intheader_length;
/*长度*/
u_intoffset;
/*偏移*/
u_chartos;
/*服务质量*/
u_int16_tchecksum;
/*校验和*/
ip_protocol=(structip_header*)(packet_content+14);
/*获得IP协议内容*/
checksum=ntohs(ip_protocol->ip_checksum);
/*获得校验和*/
header_length=ip_protocol->ip_header_length*4;
/*获得长度*/
tos=ip_protocol->ip_tos;
/*获得服务质量*/
offset=ntohs(ip_protocol->ip_off);
/*获得偏移*/
/*以太网协议变量*/
ethernet_protocol=(structether_header*)packet_content;
ethernet_type=ntohs(ethernet_protocol->ether_type);
/*获得以太网类型*/
if(ethernet_type==0x0800&&ip_protocol->ip_protocol==6)
{
u_char*mac_string;
/*以太网地址*/
printf("**************************************************\n");
printf("捕获第%d个TCP网络数据包\n",packet_number);
printf("捕获时间:
\n");
printf("%s",ctime((consttime_t*)&packet_header->ts.tv_sec));
/*获得捕获数据包的时间*/
printf("数据包长度:
\n");
printf("%d\n",packet_header->len);
printf("--------以太网协议--------\n");
/*获得以太网协议内容*/
printf("类型:
\n");
printf("%04x\n",ethernet_type);
printf("源以太网地址:
\n");
mac_string=ethernet_protocol->ether_shost;
printf("%02x:
%02x:
%02x:
%02x:
%02x:
%02x\n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
/*获得源以太网地址*/
printf("目的以太网地址:
\n");
mac_string=ethernet_protocol->ether_dhost;
printf("%02x:
%02x:
%02x:
%02x:
%02x:
%02x\n",*mac_string,*(mac_string+1),*(mac_string+2),*(mac_string+3),*(mac_string+4),*(mac_string+5));
/*获得目的以太网地址*/
ip_protocol_packet_callback(argument,packet_header,packet_content);
packet_number++;
printf("**************************************************\n");
}
}
voidmain()
{
pcap_t*pcap_handle;
/*Winpcap句柄*/
charerror_content[PCAP_ERRBUF_SIZE];
/*存储错误信息*/
char*net_interface;
/*网络接口*/
structbpf_programbpf_filter;
/*BPF过滤规则*/
charbpf_filter_string[]="";
/*过滤规则字符串*/
bpf_u_int32net_mask;
/*掩码*/
bpf_u_int32net_ip;
/*网路地址*/
net_interface=pcap_lookupdev(error_content);
/*获得可用的网络接口*/
pcap_lookupnet(net_interface,&net_ip,&net_mask,error_content);
/*获得网络地址和掩码地址*/
pcap_handle=pcap_open_live(net_interface,BUFSIZ,1,1,error_content);
/*打开网路接口*/
pcap_compile(pcap_handle,&bpf_filter,bpf_filter_string,0,net_ip);
/*编译BPF过滤规则*/
pcap_setfilter(pcap_handle,&bpf_filter);
/*设置过滤规则*/
if(pcap_datalink(pcap_handle)!
=DLT_EN10MB)
return;
pcap_loop(pcap_handle,-1,ethernet_protocol_packet_callback,NULL);
/*注册回调函数,循环捕获网络数据包,利用回调函数来处理每个数据包*/
pcap_close(pcap_handle);
/*关闭Winpcap操作*/
}
七、测试数据
本地局域网IP数据包
八、测试情况
程序运行结果图:
结论
通过两周的课程设计,增强了我的实际动手能力,通过实际的编程整合串联了我所学到的知识。
另外我还学到了作为编程人员的一些基本素质,这为我毕业后找工作奠定了基础。
通过做TCP协议分析器学习的很多网络编程知识:
1.学会了winpcap网络数据报捕获开发包的使用;
2.绑定网卡函数bind();
3.数据接受函数recv();
4.Windows套接字编程;
5.学习了原始套接字编程的基本机制;
6.学习对数据包进行协议分析的基本方法。
通过做TCP协议分析器学习的很多VisualC++Windows编程知识:
1.学会了Windows常用数据结构的使用;
2.学到了一些用VisualC++Windows编程的技巧。
参考文献
[1]甘玲邱劲《面向对象技术与VisualC++》清华大学出版社
[2]任哲《MFCWindows应用程序设计》清华大学出版社
[3]《计算机网络》北京:
机械工业出版社
[4]《VisualC++网络通信编程实用案例精选》人民邮电出版社
[5]《windows程序设计》北京大学出版社
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机网络 课程设计 编程 实现 简单 TCP 协议 分析器