网络协议分析课程设计发现网络中的活动主机.docx_第1页
网络协议分析课程设计发现网络中的活动主机.docx_第2页
网络协议分析课程设计发现网络中的活动主机.docx_第3页
网络协议分析课程设计发现网络中的活动主机.docx_第4页
网络协议分析课程设计发现网络中的活动主机.docx_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

发现网络中的活动主机 目 录一 设计目的1二 设计要求1三 概要设计23.1 设计原理23.2 数据结构设计23.1.1IP头部数据结构23.1.2ICMP头部数据结构33.3 系统流程图33.3.1主流程图 33.3.2子流程图5四 详细设计64.1.ICMP报文分析64.2.程序功能分析74.2.1使用原始套接字74.2.2定义IP头部和ICMP头部数据结构74.2.3填充并发送请求类型的ICMP报文74.2.4解析数据包9五 测试结果105.1测试中遇到的问题105.2测试结果10六总结与体会11附录及源代码12 发现网络中的活动主机 一 设计目的 IP协议的优点是简单,但缺少差错控制和查询机制,而网际控制报文协议(ICMP具有补充IP功能的作用。在网络管理中,常常要确定当前网络在红处于活动状态的主机,这时可以通过ICMP的回送和回送响应消息来完成这项工作。这课程设计的目的就是编制程序,利用ICMP数据包,发现网络中的活动主机,即ping消息的请求和应答。通过课程设计,熟悉ICMP报文的结构,对ICMP协议有更好的理解和认识,培养综合运用网络知识解决实际问题能力。二 设计要求 设计程序,其功能是发送ICMP数据包,以获取指定望段中的活动主机,并将结果显示在标准输出设备上程序的具体要求如下:1用命令形式运行scanhost为程序名;start_ip为被搜索网段;end_ip为被搜索网段的结束IP地址。如在命令行输入 scanhost 192.168.0.1 192.168.0.1002输出格式活动主机1的IP地址活动主机2的IP地址 活动主机 n的IP地址三 概要设计 3.1 设计原理 本程序使用的原始套接字生成ICMP请求/应答报文来进行活动主机的探查。这个程序使用的是回送请求和应答消息。程序的大致思想是把ICMP的数据报类型设置为回送请求,将它发送给网络上的一个IP地址,如果这个IP地址已经被占用的话,那么使用位于这个IP地址的主机上的TCP/IP软件就能接受到这个ICMP回送请求,从而返回一个ICMP回送请求(类型号为0)信息。信息封装在一个IP包中,我们需要解析该IP包,从中找到ICMP数据信息,相反,如果这个IP地址没有人使用,那么发送的ICMP回送请求在设定的延时内就不可能得到响应。 3.2 数据结构设计 3.1.1IP头部数据结构typedef struct iphdr unsigned int headlen:4; /ip头长度 unsigned int wersion:4; /ip版本号 unsigned char tos; /服务类型unsigned short totallen; /ip包总长度unsigned short id; /ip号unsigned short flag; /标记unsigned char ttl; /生存时间unsigned char prot; /协议(UDP TCP)unsigned short checksum; /校验和unsigned int sourceip; /源ipunsigned int destip; /目的ipIpHeader; 3.1.2ICMP头部数据结构 typedef struct icmphdr BYTE type; /icmp类型码,回送请求的类型码为8 BYTE code; /子类型码,保存与特定ICMP报文类型相关的细节信息 USHORT checksum; /校验和 USHORT id; /ICMP报文id号 USHORT seq; /ICMP数据报的序列号Icmpheader; 3.3 系统流程图 3.3.1主流程图 (图1) 开 始构造原始套接字,并初始化建立并初始化木的主机的Sockaddr_in数据结构dest起始IP地址-start_ip结束IP地址-end ip将start_ip填入到dest中start_iptype=icmp_echo; /设置类型 icmp_hdr-id=(ushort)getcurrentthreadid(); /设置其ID号为当前线程号 datapart=icmp_data+sizeof(icmpheader); /计算出ICMP数据报的数据部分 memset(datapart,A,datasize-sizeof(icmphearder); /填入数据 ((IcmpHeader*)icmp_data)-seq=0; /序列号 ((IcmpHeader*)icmp_data)-check_sum=0; /先将检验和置0((IcmpHeader*)icmp_data)-checksum=checksum(USHORT*) icmp_data,data_size);Checksum 为计算校验和的函数,设校验和初值为0,然后对数据每16位求异或,结果取反,便得校验和。其代码如下:unsinged long cksum=0;while (size1)cksum+=*buffer+;size-=sizeof(ushort);if(size)cksum+=*(uchar)buffer;cksum=(cksum16)+(cksum&0xffff);cksum+=(cksum16);return (ushort)(cksum); 填充ICMP报文之后,应在ICMP报文之前加上IP报头并发送出去。可调用下面的代码发送数据包。注意,这里的dest是填入目的主机的IP地址的一个sockaddr_in数据结构,IP_STRING是目的的主机的IP地址字符串。 Struct sockaddr_in_dest; Dest.sin_family=AF_INET; Dest.sin_addr.s_addr=inet_addr(IP_STRING); Sendto(sockraw,icmp_data,datasize,0,(sockaddr*)&dest,size of(dest); 4.2.4解析数据包 如果所ping的目的主机存在,那么它会发出一个回送应答包。这是一个IP包,受到后解析此数据包并获得其中的ICMP信息。根据IP报头信息中的IP报头长度字段,就可以得到ICMP报文的真实地址。ICMP数据包中的IP地址就是活动主机的IP。代码分析如下: #define ICMP_MIN 8 #define MAX_PING_PACKET_SIZE(MAX_PACKET+sizeof(IpHeader) char *recvbuf=newMAX_PING_PACKET_SIZE; struct sockaddr_in dest,from,end;int formlen=sizeof(from); int bytes=recvfrom(sockraw,recvbuf,MAX_PACKET,0,(Struct sockaddr*)&from,&fromlen) ipheader *iphdr; icmpheader *icmphdr; unsigned short iphdrlen; iphdr=(ipheader*)buf; iphdrlen=iphdr-headlen*4; /IP报头的长度 icmphdr=(icmpheader *)(buf+iphdrlen); /跳过IP头 /数据包太短 丢弃 if(bytestype!=icmp_echo_reply) return; /ID不相符,丢弃if(icmphdr-id!=(USHORT)getcurrentthreadid() return; /输出正在使用的IP地址 cout活动主机sin_addr)endl;五 测试结果 5.1测试中遇到的问题 1 找不到头文件。因为头文件存放位置错误。 2 变量没有定义。因为变量没有定义和变量名书写写错。 3 指针书写错误。 4 宏参数列表错误。 5 结构体指针传递错误。Cannot covert from struct iphdr * to struct icmphar * ip Ipheader * iphdr.因为缺少成员运算符”.”。 5.2测试结果 经反复调试,运行正常,运行结果如下(图5)图 5六总结与体会 实现利用ICMP发现网络上的活动主机。通过这次课程设计,我加深了对ICMP协议的理解,巩固了课堂知识,为以后学习网络协议打下基础。 在调试过程中难免要出现一些问题,为了能够快速地确定错误的原因,尽快的排除程序逻辑错误,通常把程序错误划分为三种类型:语法错误、运行错误和逻辑错误。在这次网络课程设计中,也发生了这样那样的错误,如变量没有定义、缺少头文件。通过查阅文献资料、请教老师和同学讨论,以及自己认真地分析与思考,逐一对错误进行了调试,使程序基本能正常运行,大体上符合了设计的意图和设计的要求。 由于网络协议比较抽象,比较难学,也学得不深入,何况还要把所学知识运用到实践中来,真是一大难题,所以一开始时,真是有点一筹莫展,网上查有关资料却总觉得不搭干。通过这次课程设计,我明白做什么事都要沉得下心,在搞任何研发工作时,遇到问题沉着冷静是特别重要的,千万不能有半点浮躁的心情。在程序的调试过程中,出现问题是正常的,关键是如何去发现问题的根源,然后去解决它。其实写程序并不是很花时间,改错才是最花时间的的事情。还有一点特别重要的是,在设计过程中或者是改错的过程中遇到棘手的问题时,借助网络去解决的确是一种很好的选择。 附录及源代码 1. scanhost.h #pragma pack(4)#pragma comment(lib,Ws2_32.lib)#define win32_LEAN_AND_MEAN#include #include #include #include #include #include /THE IP HEADERtypedef struct iphdr unsigned int headlen:4; /ip头长度 unsigned int wersion:4; /ip版本号 unsigned char tos; /服务类型unsigned short totallen; /ip包总长度unsigned short id; /ip号unsigned short flag; /标记unsigned char ttl; /生存时间unsigned char prot; /协议(UDP TCP)unsigned short checksum; /校验和unsigned int sourceip; /源ipunsigned int destip; /目的ipIpHeader;/ICMP HEADERtypedef struct icmphdr BYTE type; /icmp类型码,回送请求的类型码为8 BYTE code; /子类型码,保存与特定ICMP报文类型相关的/节信息 USHORT checksum; /校验和 USHORT id; /ICMP报文id号 USHORT seq; /ICMP数据报的序列号Icmpheader;#define ICMP_ECHO 8 /请求回送#define ICMP_ECHO_REPLY 0 /请求回应#define ICMP_MIN 8 /ICMP包头长度(最小ICMP包长度)#define STATUS_FAILED 0xFFFF /错误码#define DEF_PACKET_SIZE 32 /缺省数据报长度#define MAX_PACKET 1024 /最大数据报长度#define MAX_PING_PACKET_SIZE (MAX_PACKET + sizeof(IpHeader) /最大接受数据报长度void fill_icmp_date(char * ,int); /填充ICMP包USHORT checksum(USHORT *,int); /校验和函数void decode_resp(char*,int,struct sockaddr_in *); /找到此数据报IP地址DWORD WINAPI FindIp(LPVOID pipaddrtemp); /线程调用子函数2. scanhost.cpp #include scanhost.hWSADATA wsadata;SOCKET sockraw;struct sockaddr_in dest,from,end;int fromlen=sizeof(from);char * recvbuf=new charMAX_PING_PACKET_SIZE;unsigned int addr=0;long threadnumcounter=0,threadnumlimit=20;long *aa=&threadnumcounter;void main(int argc,char *argv)if(argc!=3)cout输入格式错误:scanhost start_ip end_ipendl;return;if(WSAStartup(MAKEWORD(2,1),&wsadata)!=0)coutWSAStartup failed:GetLastError()endl;ExitProcess(STATUS_FAILED);/创建原始套接字sockraw=WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);if(sockraw=INVALID_SOCKET)coutWSASocket() failed:WSAGetLastError()endl;ExitProcess(STATUS_FAILED); /设置读取延时 int timeout=1000; int bread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout); if(bread=SOCKET_ERROR) coutfail to set recv timeout:WSAGetLastError()endl; ExitProcess(STATUS_FAILED); timeout=1000; bread=setsockopt(sockraw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout); if(bread=SOCKET_ERROR) coutfailed to set send timeout:WSAGetLastError()endl; ExitProcess(STATUS_FAILED); memset(&dest,0,sizeof(dest); unsigned long startip,endip; dest.sin_family=AF_INET; dest.sin_addr.s_addr=inet_addr(argv1); startip=inet_addr(argv1); end.sin_family=AF_INET; end.sin_addr.s_addr=inet_addr(argv2); endip=inet_addr(argv2); HANDLE hthread; while(htonl(startip)threadnumlimit) Sleep(5000); continue; DWORD Threadid; sockaddr_in * pipaddrtemp=new(sockaddr_in); if(!pipaddrtemp) coutmemory alloc failedtype = ICMP_ECHO;icmp_hdr-id=(USHORT)GetCurrentThreadId();datapart=icmp_data+sizeof(Icmpheader);memset(datapart,A,datasize-sizeof(Icmpheader);void decode_resp(char *buf,int bytes,struct sockaddr_in *from)IpHeader *iphdr;Icmpheader *icmphdr;unsigned short iphdrlen;iphdr=(IpHeader *)buf;iphdrlen=iphdr-headlen * 4;icmphdr=(Icmpheader *)(buf+iphdrlen); /数据包太短 丢弃if(bytestype!=ICMP_ECHO_REPLY) return;if(icmphdr-id!=(USHORT)GetCurrentThreadId() return;cout活动主机sin_addr)1)cksum+=*buffer+; size-=sizeof(USHORT); if(size)cksum+=*(UCHAR*)buffer; cksum=(cksum16)+(cksum & 0xffff); cksum+=(cksum16); return (USHORT)(cksum);DWORD WINAPI FindIp(LPVOID pipaddrtemp)InterlockedIncrement(aa); char icmp_dataMAX_PACKET; memset(icmp_data,0,MAX_PACKET); int datasize=DEF_PACKET_SIZE; datasize+=sizeof(Icmpheader); fill_icmp_data(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论