网络通信编程 原始套接字程序设计PPT课件_第1页
网络通信编程 原始套接字程序设计PPT课件_第2页
网络通信编程 原始套接字程序设计PPT课件_第3页
网络通信编程 原始套接字程序设计PPT课件_第4页
网络通信编程 原始套接字程序设计PPT课件_第5页
已阅读5页,还剩91页未读 继续免费阅读

下载本文档

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

文档简介

.,1,第四章,原始套接字,.,2,内容提要,1.使用原始套接字2.套接字选项3.ICMP编程4.使用IP头包含选项5.网络嗅探器实例,.,3,1.使用原始套接字,利用原始套接字(RawSocket),可访问底层传输协议。,原始套接字(RawSocket)与标准套接字区别,.,4,使用原始套接字可以做什么?实现一些实用工具(ping,traceroute)。可对IP头,TCP头,UDP头,ICMP头等进行操作。原始套接字使用SOCK_RAW套接字类型来创建的,目前只有Winsock2提供了对它的支持。无论MicrosoftWindowsCE还是老版本的Windows95(无Winsock2升级)均不能利用原始套接字。,.,5,创建原始套接字,原始套接字类型在IP头中使用预定义的协议(如ICMP)在IP头中使用自定义的协议(使用IP头包含选项),.,6,创建原始套接字使用socket()或WSASocket()创建原始套接字。例:创建原始套接字使用预定义协议:SOCKETs;S=socket(AF_INET,SOCK_RAM,IPPROTO_ICMP);/ORS=WSAsocket(AF_INEF,SOCK_RAM,IPPROTO_ICMP,NULL,0,WSA_FLAG_OVERLAPPED);,.,7,使用自定义协议使用IGMP、UDP、IP或者原始IP,只需分别设置IPPROTO_IGMP、IPPROTO_UDP、IPPROTO_IP或IPPROTO_RAW即可。注意:在WindowsNT4、Windows98以及Windows95(安装Winsock2)操作系统中,创建原始套接字时,只能使用ICMP。协议标志IPPROTO_UDP、IPPROTO_IP以及IPPROTO_RAW均要求使用套接字选项IP_HDRINCL,而该选项在上述平台下都是不支持的。Windows2000提供了对IP_HDRINCL选项的支持,所以能够处理IP头(IPPROTO_RAW)、TCP头(IPPROTO_TCP)以及UDP头(IPPROTO_UDP)。无论是否设置IP_HDRINCL选项,原始套接字上接收到的数据都会包含IP头。,.,8,使用原始套接字可以对底层传输机制加以控制,所以有些人将其用于不法用途,,.,9,套接字选项操作函数getsocketopt()获取套接字选项信息。intgetsocketopt(SOCKETs,/套接字描述符intlevel,/选项级别intoptname,/选项名称char*optval,/选项值int*optlen/选项长度);setsocketopt()设置套接字选项。intsetsocketopt(SOCKETs,intlevel,intoptname,constchar*optval,intoptlen);,2.套接字选项,.,10,选项级别:协议的层次对应选项级别应用层:SOL_SOCKET传输层:IPPROTO_TCP、IPPROTO_UDP网络层:IPPROTO_IP不同级别属性不同,同一级别的不同协议的属性不同,因此必须指定level参数例:IntnTime=2*1000setsockopt(s,SOL_SOCKET,SO_RCVTIMEO,(char*)IPPROTO_ICMP指定使用ICMP,.,PING程序执行步骤,1、创建协议类型为IPPROTO_ICMP的原始套接字,设置套接字的属性。2、创建并初始化ICMP封包。3、调用sendto函数向远程主机发送ICMP请求。4、调用recvfrom函数接收ICMP响应。,.,/Ping.h/声明IP头数据结构typedefstruct_IPHeader/20字节的IP头UCHARiphVerLen;/版本号和头长度(各占4位)UCHARipTOS;/服务类型USHORTipLength;/封包总长度,即整个IP报的长度USHORTipID;/封包标识,惟一标识发送的每一个数据报USHORTipFlags;/标志和片偏移UCHARipTTL;/生存时间,就是TTLUCHARipProtocol;/协议,可能是TCP、UDP、ICMP等USHORTipChecksum;/校验和ULONGipSource;/源IP地址ULONGipDestination;/目标IP地址IPHeader,*PIPHeader;,PING程序代码,.,/ICMP头数据结构typedefstructicmp_hdrunsignedcharicmp_type;/消息类型unsignedcharicmp_code;/代码unsignedshorticmp_checksum;/校验和unsignedshorticmp_id;/用来惟一标识此请求的ID号,通常设置为进程IDunsignedshorticmp_sequence;/序号unsignedlongicmp_timestamp;/数据传输时间ICMP_HDR,*PICMP_HDR;/ICMP回送请求的数据结构typedefstruct_EchoRequestICMP_HDRicmphdr;charcData32;ECHOREQUEST,*PECHOREQUEST;,.,/ICMP回送应答的数据结构#defineREQ_DATASIZE32typedefstruct_EchoReplyIPHeaderiphdr;ECHOREQUESTechoRequest;ECHOREPLAY,*PECHOREPLAY;/校验和的计算/以16位的字为单位将缓冲区的内容相加,如果缓冲区长度为奇数,/则再加上一个字节。它们的和存入一个32位的双字中USHORTchecksum(USHORT*buff,intsize);,/Ping.cpp#include#include#pragmacomment(lib,WS2_32)/链接到WS2_32.lib#include#includeping.h,.,USHORTchecksum(USHORT*buff,intsize)u_longcksum=0;while(size1)/将数据以字为单位累加到cksum中cksum=cksum+*buff;buff=buff+1;size=size-sizeof(USHORT);/等价于size=size-2;if(size=1)/共有奇数个字节将最后一个字节扩展为字,再累加USHORTu=0;u=(USHORT)(*(UCHAR*)buff);cksum=cksum+u;/校验位计算/高16位和低16位相加cksum=(cksum16)+(cksum,位右移运算符右边的值依次被移出了,左边的位置依次放0,校验位计算(1)将32位的chsum高16位和低16位相加(2)自加当前数的高16位(3)取反并转换为16位,.,intmain()WSADATAwsaData;WORDversion=MAKEWORD(2,2);intret=WSAStartup(version,.,/创建ICMP封包(回送请求)ECHOREQUESTechoReq;/填写ICMP封包数据echoReq.icmphdr.icmp_type=8;/请求一个ICMP回显echoReq.icmphdr.icmp_code=0;echoReq.icmphdr.icmp_id=(USHORT)GetCurrentProcessId();echoReq.icmphdr.icmp_checksum=0;echoReq.icmphdr.icmp_sequence=0;/填充数据部分,可以为任意memset(/Setsbufferstoaspecifiedcharacter.,.,/开始发送和接收ICMP封包USHORTnSeq=0;SOCKADDR_INfrom;intnLen=sizeof(from);while(TRUE)staticintnCount=0;intnRet;if(nCount+=4)break;echoReq.icmphdr.icmp_checksum=0;/GetTickCount()系统开始后,已经经过的毫秒数echoReq.icmphdr.icmp_timestamp=GetTickCount();echoReq.icmphdr.icmp_sequence=nSeq+;echoReq.icmphdr.icmp_checksum=checksum(USHORT*),.,/接收回送应答包ECHOREPLAYechoReply;nRet=recvfrom(sRaw,(char*),.,/下面开始解析接收到的封包if(nRetsizeof(ECHOREPLAY)printf(Toofewbytesfrom%sn,inet_ntoa(from.sin_addr);/接收到的数据中包含IP头,IP头大小为20个字节if(echoReply.echoRequest.icmphdr.icmp_type!=0)/回显printf(nonechotype%drecvdn,echoReply.echoRequest.icmphdr.icmp_type);return-1;if(echoReply.echoRequest.icmphdr.icmp_id!=GetCurrentProcessId()printf(someoneelsespacket!n);return-1;,.,printf(%dbytesReplyfrom%s:,nRet,inet_ntoa(from.sin_addr);printf(icmp_seq=%d.,echoReply.echoRequest.icmphdr.icmp_sequence);intnTick=GetTickCount();printf(time:%dms,nTick-echoReply.echoRequest.icmphdr.icmp_timestamp);printf(TTL=%d,echoReply.iphdr.ipTTL);printf(n);Sleep(1000);WSACleanup();/释放Winsock库return0;,.,64bytesReplyfrom192.168.0.2:icmp_seq=0.time:0msTTL=6464bytesReplyfrom192.168.0.2:icmp_seq=1.time:0msTTL=6464bytesReplyfrom192.168.0.2:icmp_seq=2.time:0msTTL=6464bytesReplyfrom192.168.0.2:icmp_seq=3.time:0msTTL=64,PING程序运行结果,.,51,Traceroute(追踪路由)利用Traceroute可侦测出到达网络内特定主机,中途需经过哪些路由器(IP地址)。利用Ping,使用IP选项头内的记录路由选项,侦测中途经过的路由器IP地址,但Ping最多只支持9跳。,TRACEROUTE程序分析,.,52,.,53,若网络较大,穿过的路由器不止9个,应换用Traceroute。实现Traceroute程序的方法基本思想:多次发送数据包,TTL递增,TTL为0时返回一条ICMP报文。例:路由跟踪程序(采用发送UDP数据包)创建两个套接字:sRaw用于接收ICMP数据包sSend用于发送TTL不断增加的UDP数据报,.,Traceroute程序主要代码,typedefstructicmp_hdrunsignedcharicmp_type;/消息类型unsignedcharicmp_code;/代码unsignedshorticmp_checksum;/校验和/下面是回显头unsignedshorticmp_id;/用来惟一标识此请求的ID号,通常设置为进程IDunsignedshorticmp_sequence;/序列号unsignedlongicmp_timestamp;/时间戳ICMP_HDR,*PICMP_HDR;,.,BOOLSetTTL(SOCKETs,intnValue)intret=setsockopt(s,IPPROTO_IP,IP_TTL,(char*),.,voidmain()char*szDestIp=“202.199.25.20”;/目的地址charrecvBuf1024=0;/创建用于接收ICMP封包的原始套节字,绑定到本地端口SOCKETsRaw=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);sockaddr_inin;in.sin_family=AF_INET;in.sin_port=0;in.sin_addr.S_un.S_addr=INADDR_ANY;if(bind(sRaw,(sockaddr*),.,/创建用于发送UDP封包的套节字SOCKETsSend=socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_INdestAddr;destAddr.sin_family=AF_INET;destAddr.sin_port=htons(22);destAddr.sin_addr.S_un.S_addr=inet_addr(szDestIp);intnTTL=1;intnRet;ICMP_HDR*pICMPHdr;intnTick;SOCKADDR_INrecvAddr;do/设置UDP封包的TTL值SetTTL(sSend,nTTL);nTick=GetTickCount();/发送这个UDP封包nRet=sendto(sSend,hello,5,0,(sockaddr*),.,if(nRet=SOCKET_ERROR)printf(sendto()failedn);break;/等待接收路由器返回的ICMP报文intnLen=sizeof(recvAddr);nRet=recvfrom(sRaw,recvBuf,1024,0,(sockaddr*),.,/解析接收到的ICMP数据pICMPHdr=(ICMP_HDR*),.,60,4.使用IP头包含选项,创建原始套接字后使用IP_HDRINCL套接字选项可对IP头进行操作,同时也能操作TCP或UDP头(或封装在IP内的其他任何协议)。使用IP_HDRINCL选项时,必须针对每一次发送调用,向IP头内自行填充内容。同时还需填写封装在其中的其他协议头。相关协议报文格式,.,固定部分,可变部分,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,数据部分,首部,传送,IP数据报,发送在前,IP数据报格式,.,可变部分,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,数据部分,首部,传送,IP数据报,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,数据部分,首部,传送,IP数据报,固定部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,标志(flag)占3位,目前只有前两位有意义。标志字段的最低位是MF(MoreFragment)。MF1表示后面“还有分片”。MF0表示最后一个分片。标志字段中间的一位是DF(DontFragment)。只有当DF0时才允许分片。,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,生存时间(8位)记为TTL(TimeToLive),这是为了限制数据报在网络中的生存时间,用“跳数”作为TTL的单位。数据报每经过一个路由器,其TTL值就减1。,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,运输层,网络层,首部,TCP,UDP,ICMP,IGMP,OSPF,数据部分,IP数据报,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,首部,0,4,8,16,19,24,31,版本,标志,生存时间,协议,标识,区分服务,总长度,片偏移,填充,首部检验和,源地址,目的地址,可选字段(长度可变),位,首部长度,数据部分,固定部分,可变部分,.,IP数据报首部的可变部分,IP首部的可变部分就是一个选项字段,用来支持排错、测量以及安全等措施,内容很丰富。选项字段的长度可变,从1个字节到40个字节不等,取决于所选择的项目。增加首部的可变部分是为了增加IP数据报的功能,但这同时也使得IP数据报的首部长度成为可变的。这就增加了每一个路由器处理数据报的开销。,.,77,typedefstruct_IPHeader/20字节的IP头UCHARiphVerLen;/版本号和头长度(各占4位)UCHARipTOS;/服务类型USHORTipLength;/整个IP报文长度USHORTipID;/封包标识USHORTipFlags;/标志、片偏移量UCHARipTTL;/生存时间TTLUCHARipProtocol;/协议(TCP、UDP、ICMP等)USHORTipChecksum;/校验和ULONGipSource;/源IP地址ULONGipDestination;/目标IP地址IPHeader,*PIPHeader;,网络编程中IP头对应结构体声明,.,78,UDP头简单。长度仅为8个字节,而且只包含了四个字段,格式如图所示。,由于UDP是一种不能保证数据可靠传输的协议,所以校验和的计算是可选的。UDP校验和除覆盖了UDP头之外,还同时覆盖了实际的数据,此外还包括IP头的一部分。,.,79,typedefstruct_UDPHeaderUSHORTsourcePort;/源端口号USHORTdestinationPort;/目的端口号USHORTlen;/封包长度USHORTchecksum;/校验和UDPHeader,*PUDPHeader;,.,80,计算UDP校验和的附加字段叫作“伪首部”。UDP校验和基于如下几个域:32位源IP地址(IP头)32位目标IP地址(IP头)8位字段(全零)8位协议16位UDP长度16位源端口号16位目标端口号16位UDP长度16位UDP校验和UDP数据,.,81,发送原始UDP封包的步骤首先以IPPOTO_UDP为协议类型创建一个原始套接字,打开原始套接字上的IP_HDRINCL选项;然后构建UDP封包(先设置IP头,再设置UDP头,最后设置数据);初始化完整的UDP封包之后,调用sendto函数即可将它发送。例:发送原始UDP封包,.,发送原始UDP封包,intmain()/输入参数信息charszDestIp=10.16.115.88;/=填写目的IP地址charszSourceIp=127.0.0.1;/ipTTL=128;pIphdr-ipProtocol=IPPROTO_UDP;pIphdr-ipSource=inet_addr(szSourceIp);pIphdr-ipDestination=inet_addr(szDestIp);pIphdr-ipChecksum=checksum(USHORT*)pIphdr,sizeof(IPHeader);/UDP头UDPHeader*pUdphdr=(UDPHeader*),.,ComputeUdpPseudoHeaderChecksum(pIphd

温馨提示

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

评论

0/150

提交评论