为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

[计算机]发现网络中的活动主机报告及源代码

2017-10-16 23页 doc 80KB 35阅读

用户头像

is_562397

暂无简介

举报
[计算机]发现网络中的活动主机报告及源代码[计算机]发现网络中的活动主机报告及源代码 目 录 一(课程设计目的…………………………………………………………………2 二. 课程设计要求…………………………………………………………………2 三(相关知识………………………………………………………………………2 四(课程设计分析…………………………………………………………………4 五(程序流程图……………………………………………………………………7 六(程序运行结果截图……………………………………………………………10 七. 课程设计心得……………………………………………...
[计算机]发现网络中的活动主机报告及源代码
[计算机]发现网络中的活动主机报告及源代码 目 录 一(课程设计目的…………………………………………………………………2 二. 课程设计要求…………………………………………………………………2 三(相关知识………………………………………………………………………2 四(课程设计分析…………………………………………………………………4 五(程序图……………………………………………………………………7 六(程序运行结果截图……………………………………………………………10 七. 课程设计心得…………………………………………………………………10 八.附录:参考文献……………………………………………………………… 11 0 一(课程设计目的: IP的优点是简洁,但缺少差错控制和查询机制,而网际控制报文协议(ICMP)具有补充IP功能的作用。在网络管理中,常常要确定当前网络中处于活动状态的主机,这时可以通过使用ICMP的回送和回送响应消息来完成这项工作。本课程设计的目的就是编制程序,利用ICMP数据包,发现指定网段中的活动主机。通过课程设计,使学生更加熟悉ICMP报文的结构,对ICMP协议有更好的理解和认识。 二(课程设计要求: 设计程序,其功能是发送ICMP数据包,以获取指定网段中的活动主机,并将结果显示在输出上。 程序的具体要求如下: 1)用命令行形式运行: scanhost Start_IP End_IP 其中scanhost为程序名;Start_IP为被搜索网段的开始IP地址;End_IP 为被搜索网段的 结束IP地址。 2)输出格式为: 活动主机1 活动主机2 …… 三(相关知识: 编制程序前首先要对ICMP报文的格式有一定的了解,ICMP报文是在IP数据报内部传输的,其结构如图10-1所示: IP数据报 IP首部 ICMP报文 ICMP报文的格式如图10-2所示: 0 7 8 15 16 31(位) 类型字段 代码字段 校验和字段 1 (不同类型和代码有不同内容) 所有报文的前4个字节都是一样的,但是其它字节则互不相同。其中类型字段可以有15个不同的值,以描述特定类型的ICMP报文,某些ICMP报文还使用代码字段的值来进一步描述不用的条件。按验和字段为2字节,校验的范围是整个ICMP报文。检验和是必须的,其计算方法与IP协议头部校验和的计算方法一样。 各种类型的ICMP报文如图10-3所示(ICMP报文类型),不同类型由报文中的类型字段和代码字段来共同决定。 类 型 代 码 描 述 0 0 回送响应(PING应答) 3 目的不可达 0 网络不可达 1 主机不可达 2 协议不可达 3 端口不可达 4 需要进行分片但设置了禁止分片比特 5 源主机选择路由失败 6 无法识别目的网络 7 无法识别目的主机 8 源主机被隔离 9 目的网络被禁止 10 目的主机被禁止 11 由于服务类型(TOS),网络不可达 12 由于服务类型(TOS),主机不可达 13 由于过滤,通信被强行禁止 14 主机越权 15 优先权终止生效 4 0 源端被关闭(基本流控制) 5 重定向 0 对网络重定向 1 对主机重定向 2 对服务类型和网络重定向 3 对服务类型和主机重定向 8 0 回送请求(PING请求) 9 0 路由器通告 10 0 路由器请求 11 超时 0 传输期间生存期减为0 1 数据报组装期间生存期减为0 2 12 参数问题 0 各种IP头部错误 1 缺少必须的选项 13 0 时间戳请求 14 0 时间戳应答 15 0 信息请求(已作废) 16 0 信息应答(已作废) 17 0 地址掩码请求 18 0 地址掩码应答 10-3 ICMP报文类型 本课程设计的目的是发现网络中的活动主机,就是使用ICMP的回送和回送响应消息发现网络中的活动主机,即Ping消息的请求和应答。那幺,发送的ICMP的数据包类型设置为回送请求(类型号为8)。 四(课程设计分析: 本程序使用原始套接字生成ICMP报文来进行活动主机的探查。这个程序使用的是回送请求与应答消息。程序的大致思想是把ICMP的数据包类型设置为回送请求,将它发送给网络上的一个IP地址,如果这个IP地址已经被占用的话,那幺使用位于这个IP地址的主机上的TCP/IP软件就能够接收到这个ICMP回送请求,从而返回一个ICMP回送响应(类型号为0)信息。信息封装在一个IP包中,我们需要解析该IP包,从中找到ICMP数据信息。相反,如果这个IP地址没有人使用,那幺发送的ICMP回送请求在设定的延时内就不可能得到响应。 在初始化原始套接字之后,本程序就要开始在一个IP网段内寻找活动主机。因为要寻找的主机可能很多,为节省时间可以采用多线程编程。下面接结合核心代码对程序的具体实现进行讲解,同时为使程序流程更加清晰,去掉了错误检查等保护性代码。 1.使用原始套接字 为了实现发送/监听ICMP报文,必须使用原始套接字,创建原始套接字的代码如下: socket sockRaw; sockRaw = WSAocket (AF_INET, sock_Raw, IPPROTO_ICMP, NULL, 0, WSA_FLAG_OVERLAPPED); 在WSASocket函数中,我们使用IPPROTO_ICMP示接收ICMP数据包,为了使 3 用发送超时设置(设置SO_RCVTIMEO或SO_SNDTIMEO),必须将标志位置为WSA_FLAG_OVERLAPPED。然后调用setsockopt函数设置读取延迟。 Int timeout=1000; Setsockopt(sockRaw,SQL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(time out);setsockopt(sockRaw,SQL_socket,SO_SNDTIMEO,(char*)&timeout,sizeof (timeout)) 在setsockopt函数中,sockRaw是之前创建的原始套接字,设置SQL_SOCKET表明使用基本套接字处理ICMP报文。设置SO_RCVTIMEO表示使用接收超时设置,SO_SNDTIMEO表示使用发送超时设置,在这里,超时时间均设置为1000ms。 2(定义IP头部和ICMP头部的数据结构 由于socket发送/捕获的是IP包,因此要分别定义IP头部的数据结构ICMP头部数据结构。 //IP报头的数据结构 typedef struct iphdr{ unsigned int headlen:4; //IP头长度 unsigned int version:4; //IP版本号 unsigned char tos; //服务类型 unsigned short totallen; //IP包总长度 unsigned short id;; //ID号 unsigned short flag; //标记 unsigned char ttl; //生存时间 unsigned char prot; //协议(UDP TCP) nsigned short checksum; //校验和 unsigned int sourceIP; //源IP unsigned int destIP; //目的IP }IpHeader; //ICMP头部的数据结构 typedef struct icmphdr{ BYTE type; //ICMP类型码,回送请求的类型码为8 BYTE code; //子类型码,保存与特定ICMP报文类型相关细节信息 USHORT checksum; //校验和 USHORT id; //ICMP报文ID号(一般用进程号作ID) USHORT seq; //ICMP数据报的序列号 }IcmpHeader; 3(填充并发送回送请求类型的ICMP报文 为了使收到数据包的目的主机发送响应,我们需要向目的主机发送回送请求类型的ICMP报文。从图10-3中可知,回送请求的类型号为8。因此ICMP报文 4 的填充代码如下: 请求回送 #define ICNP_ECHO 8 //#define DEF_PACKET_SIZE 32 //缺省数据报长度 #define MAX_PACKET 1024 //最大数据块长度 char icmp_data[MAX_PACKET]; //ICMP数据报最大可能的长度 memset(icmp_data,0,MAX_PACKET); //将数据报清空初始化 int datasize=DEF_PACKET_SIZE; //ICMP数据报报文体的缺省长度 datasize+=sizeof(IcmpHeader); //再加上ICMP头部的长度 IcmpHeader*icmp_hdr: Char *datapart; Icmp_hdr = (IcmpHeader*)icmp_data; Icmp_hdr->type = ICMP_ECHO; //设置类型 Icmp_hdr->id = (USHORT)GetCurrentThreadId(); //设置其ID号为当前线程号 Datapart = icmp_data + sizeof(IcmpHeader); //计算出数据报的数据部分 填入数据 Memset(datapart,A,datasize-sizeof(IcmpHeader)); // ((IcmpHeader*)icmp_data)->seq= 0; //序列号为0 ((IcmpHeader*)icmp_data)->checksum = 0; //先将校验和置0 ((IcmpHeader*)icmp_data)->checksum = checksum((USHORT*)icmp_data,datasize); checksum为校验和的函数,设校验和初值为0 ,然后对数据每16为求异或,结果取反,便得校验和。其代码如下: USHORT checksum(USHORT *buffer, int size) 计算校验和 { unsigned long cksum = 0; while(size>1) { cksum+=*buffer++; size -=sizeof(USHORT); } if(size) { cksum += (UCHAR*)buffer; } cksum = (cksum >> 16)+(cksum & 0xffff); cksum +=(cksum >> 16); return(USHORT)(-cksum); } 填充ICMP报文之后,应在ICMP报文之前加上IP报头并发送出去。可调用下面的代码发送数据包。注意,这里的DEST是填入目的主机IP地址的一个 5 sockaddr_in数据结构,IP—STRING是目的主机的IP地址字符串。 Struct sockaddr_in dest; dest.sin_family = AF_INET; dest.sin_addr.s_addr = inet_addr(IP_STRING); //填入搜索的IP地址 sendto(sockRaw,icmp_data,datasize,0,(sockaddr*)&dest,sizeof(dest)); 4.解析数据包 如果所Ping的目的主机所在,那么它会发送一个回送应答包。这是一个IP包,收到后解析此数据包并获取其中的ICMP信息。根据IP报头信息中的IP报头长度字段,就可以得到ICMP报文的真实地址。ICMP数据包中的IP地址就是活动主机的IP。代码如下: #define ICMP_MIN 8 //ICMP报文头长度(最小ICMP报文长度) #define MAX_PING_PACKET_SIZE (MAX_PACKET + SIZEOF(IPHeader)) char *recvbuf=new char[MAX_PING_PACKET_SIZE]; //保证大与发送包的大小 //from是一个sockaddr_in数据结构,用于保存响应的目的的主机的地址 struct sockaddr_in from; int fromlen = sizeof(from); int bytes = recvfrom(sockRaw,recvbuf,MAX_PACKET, 0,(struck 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!=(USHOT)GetCurrentThreadId()) return; //输出正在使用的IP地址。 Cout<<”活动主机:”<sin_addr)< #include #include #include #include #include #include typedef struct iphdr { unsigned int headlen:4; unsigned int version:4; unsigned char tos; unsigned short totallen; 10 unsigned short id; unsigned short falg; unsigned char ttl; unsigned char prot; unsigned short checksum; unsigned int sourceIP; unsigned int destIP; }IpHeader; typedef struct icmphdr { BYTE type; BYTE code; USHORT checksum; USHORT id; USHORT seg; }IcmpHeader; #define ICMP_RCHO 8 11 #define ICMP_RCHO_REPLY 0 #define ICMP_MIN 8 #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_data(char *,int); USHORT checksum(USHORT *,int); void decode_resp(char *,int,struct sockaddr_in *); DWORD WINAPI FindIP(LPVOID pIPAddrTemp); WSADATA wsaData; SOCKET sockRaw; struct sockaddr_in dest,from,end; int fromlen =sizeof(from); char *recvbuf=new char[MAX_PING_PACKET_SIZE]; unsigned int addr=0; 12 long ThreadNumCounter=0,ThreadNumLimit=20; long *aa=&ThreadNumCounter; void main(int argc,char *argv[]) { /*if(argc!=3) { cout<<"输入格式错误: start_ip end_ip"<ThreadNumLimit) { Sleep(5000); continue; } DWORD ThreadID; sockaddr_in *pIPAddrTemp=new (sockaddr_in); if(!pIPAddrTemp) { cout<<"memory alloc failed"<type=ICMP_RCHO; icmp_hdr->id=(USHORT)GetCurrentThreadId(); datapart=icmp_data+sizeof(IcmpHeader); memset(datapart,'A',datasize-sizeof(IcmpHeader)); } 18 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_RCHO_REPLY)return; if(icmphdr->id!=(USHORT)GetCurrentThreadId())return; 19 cout<<"活动主机: "<sin_addr)<1) { cksum+=*buffer++; size-=sizeof(USHORT); } if(size) { 20 cksum+=*(UCHAR*)buffer; } cksum=(cksum>>16)+(cksum& 0xffff); cksum+=(cksum>>16); return (USHORT)(~cksum); } DWORD WINAPI FindIP(LPVOID pIPAddrTemp) { InterlockedIncrement(aa); char icmp_data[MAX_PACKET]; memset(icmp_data,0,MAX_PACKET); int datasize=DEF_PACKET_SIZE; datasize+=sizeof(IcmpHeader); fill_icmp_data(icmp_data,datasize); ((IcmpHeader*)icmp_data)->checksum=0; ((IcmpHeader*)icmp_data)->seg=0; 21 ((IcmpHeader*)icmp_data)->checksum=checksum((USHORT*)ic mp_data,datasize); int bwrote=sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr *)pIPAddrTemp,sizeof(dest)); int n=0; if(bwrote==SOCKET_ERROR) { if(WSAGetLastError()==WSAETIMEDOUT) { cout<<"timed out"<
/
本文档为【[计算机]发现网络中的活动主机报告及源代码】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索