IP数据报的封装过程设计.docx
- 文档编号:10214879
- 上传时间:2023-02-09
- 格式:DOCX
- 页数:23
- 大小:78.21KB
IP数据报的封装过程设计.docx
《IP数据报的封装过程设计.docx》由会员分享,可在线阅读,更多相关《IP数据报的封装过程设计.docx(23页珍藏版)》请在冰豆网上搜索。
IP数据报的封装过程设计
TCP/IP
课
程
设
计
报
告
课程设计任务书
题目:
IP数据包的封装过程设计
主要内容:
1、分析IP协议首部,定义数据结构,用自然语言写出封装过程中的各个函数。
2、设计校验算法、分片处理、队列处理等。
包括数据结构、处理函数、处理流程。
基本要求:
4人组合成一个小组,分别做ip协议中的输入模块、输出模块以及校验算法等。
主要参考资料:
1.TCP/IP详解 卷2:
实现(美)莱特等著机械工业出版社
2.TCP/IP详解 卷1:
协议(美)史蒂文斯著机械工业出版社
3.用TCP/IP进行网际互连第二卷(美)DouglasE.Comer著电子工业出版社
摘要:
运输层把它的数据和首部部分发送到IP层,IP层收到数据包后,先在主机的缓存中进行排队,然后,进行封装,再加上IP首部后成为整个数据链路层的收据部分。
其中在添加IP首部的时候,对IP首部的实现加以设计,以及IP层在接受运输层传下来的数据进行队列和分片处理,同时对IP数据包的首部进行进行检验和计算。
重要的是设计出队列处理、分片处理以及检验和处理的实现过程。
一、设计内容………………………………………5
二、模块的划分……………………………………5
三、设计思路……………………………………5
四、变量的定义……………………………………8
五、设计流程图……………………………………6
六、心得体会……………………………………15
七、参考文献………………………………………15
一、设计内容:
1、分析IP协议首部,定义数据结构,用自然语言写出封装过程中的各个函数。
2、设计检验和算法、进行分片处理、队列处理。
包括数据结构、处理函数、处理流程。
二、模块的划分:
根据课程设计所要设计的内容以及设计要求,我们把IP数据包的封装过程设计大致分为五个模块,分别为:
整体结构模块及其实现过程、IP数据包的首部格式及其实现模块、IP数据包的分片处理及其实现模块、IP数据包首部检验算法及其实现模块、队列处理及其实现模块。
我负责的模块是整体结构模块及其实现过程和队列处理及其实现过程两个模块。
三、模块的设计思路:
a、IP数据包的封装过程
互联网络层是TCP/IP协议参考模型中的关键部分。
IP协议把传输层送来的消息组装成IP数据包,并把IP数据包传送给数据链层。
IP协议在TCP/IP协议族中处于核心地位,IP协议制定了统一的IP数据包格式,以消除个通信子网中的差异,从而为信息发送方和接收方提供了透明的传输通道。
数据封装入IP数据包后,传递到数据链路层,在网际间逐“跳”进行传送。
在那里,数据包继续进行封装,IP报头和所有数据都封装成链路层帧,如以太网帧。
IP数据包可以封装成许多这样的数据链路层帧,然后在网络间进行路由传送。
在每一跳处,IP数据包都从数据链路层帧中剥离出来,然后重新打包成帧以传送至下一跳。
在此过程中,IP数据包都不发生变化(除了一些控制字段),直至其到达最终目的地。
IP数据包在概念上类似于以太网或其它数据链路层的帧。
二者最重要的区别是,IP数据包旨在促进网络间的传输,而数据链路层帧仅用于在物理网络中的直接传送。
IP报头中的字段用于管理网络间的数据包传送,它们包括信息传递所需的关键信息,如目的设备的地址、帧类型标识、控制位等。
b、数据包的首部格式
04816192431
版本
报头标长
服务类型
总长度
标识
标志
片偏移
生存时间
协议
头校验和
源IP地址
目的IP地址
选项
填充域
数据部分
IPv4首部一般是20字节长。
在以太网帧中,IPv4包首部紧跟着以太网帧首部,同时以太网帧首部中的协议类型值设置为080016。
IPv4提供不同,大部分是很少用的选项,使得IPv4包首部最长可扩展到60字节(总是4个字节4个字节的扩展)
版本(Version):
长度4比特。
标识目前采用的IP协议的版本号。
一般的值为0100(IPv4),IPv6的值(0110)
首部长度(HeaderLength):
长度4比特。
这个字段的作用是为了描述IP包头的长度,因为在IP包头中有变长的可选部分。
IP包头最小长度为20字节,由于变长的可选部分最大长度可能会变成24字节。
服务类型(TypeofService):
长度8比特。
这个子段可以拆分成两个部分:
Precedence和TOS。
TOS目前不太使用。
而Precedence则用于QOS应用。
(TOS字段的详细描述RFC13401349)
长度(TotalLength):
长度16比特。
IP包最大长度65535字节。
标识(Identifier):
长度16比特。
该字段和Flags和FragmentOffest字段联合使用,对大的上层数据包进行分段(fragment)操作。
标志(Flags):
长度3比特。
该字段第一位不使用。
第二位是DF位,DF位设为1时表明路由器不能对该上层数据包分段。
如果一个上层数据包无法在不分段的情况下进行转发,则路由器会丢弃该上层数据包并返回一个错误信息。
第三位是MF位,当路由器对一个上层数据包分段,则路由器会在除了最后一个分段的IP包的包头中将MF位设为1。
片偏移(FragmentOffset):
长度13比特。
该字段对包含分段的上层数据包的IP包赋予序号。
由于IP包在网络上传送的时候不一定能按顺序到达,这个字段保证了目标路由器在接受到IP包之后能够还原分段的上层数据包。
到某个包含分段的上层数据包的IP包在传送是丢失,则整个一系列包含分段的上层数据包的IP包都会被要求重传。
生存时间(TTL):
长度8比特。
当IP包进行传送时,先会对该字段赋予某个特定的值。
当IP包经过每一个沿途的路由器的时候,每个沿途的路由器会将IP包的TTL值减少1。
如果TTL减少为0,则该IP包会被丢弃。
这个字段可以防止由于故障而导致IP包在网络中不停被转发。
协议(Protocol):
长度8比特。
标识了上层所使用的协议。
校验和:
16位,是IPv4数据报包头的校验和。
源IP地址:
32位。
目的IP地址:
32位。
c、分片处理设计思路
在应用程序中,必须关心IP数据的长度。
如果它超过网络的MTU,那么就要对IP数据报进行分片。
如果需要,源目的端之间的每个网络都要进行分片,并不只是发送端主机连接第一个网络才这样做。
在此文中,将讨论IP分片的一些原理及其在分片中所需要的几个元素(此文只讨论MTU最大传输单位和MSS最大数据分段),本文对以太网的例子作了初略的分解。
关键字:
IP分片,MTU,MSS引言分片是分组交换的思想体现,也是IP协议解决的两个主要问题之一。
在IP协议中的分片算法主要解决异种网最大传输单元(MTU)的不同.但是分组在传输过程中不断地分片和重组会带来很大的工作量还会增加一些不安全的因素。
d、校验和设计思路
在计算IP数据包首部校验和时我们所采用的是二进制反码求和,具体方法是这样的:
0和0相加是0,0和1相加是1,1和1相加是0但要产生一个进位1,加到下一列.若最高位相加后产生进位,则最后得到的结果要加1.
首先,把IP数据包的校验和字段置为0;其次,把首部看成以16位为单位的数字组成,依次进行二进制反码求和;最后,把得到的结果存入校验和字段中。
e、队列处理模块的设计思路
由于运输层一次传输下来的数据不止一个,可能有很多个,进入到IP层是必须对上层传输下来的数据进行排队,因此IP层必须要有一个来存放多个数据包的缓冲区。
以便使上层的传下来的数据能够很顺序的传入给数据链路层。
传入的分组放在缓存区中,并将其传递给适当的协议软件做进一步处理。
同时,应用程序产生的输出数据也必须分组的形式存储在缓冲区中,并将其传递给网络硬件设备传送出去。
由于IP数据报可能有64K八位组长,倘若是缓冲区大得足以容纳任意长度地数据包,有效内存储空间根本划分不了几个缓冲区就会被耗尽。
再者,短小的分组才是常规的,而长数据报并不多见,因此,使用大缓冲区会导致内存空间的实际效率很低,与此同时系统却没有足够多的缓冲区来满足通信量的要求。
实际上,采用大缓冲区的设计者们通常都会选择一个系统能够处理的数据包的最大长度限制D,然后是缓冲区足够大,可以容纳长度为D的数据包外加物理网络帧头。
采用这种这种方法是在允许使用较长的数据包和能够给正常的通信量提供足够多的缓冲区之间的折衷。
因此,D的大小不但取决于缓冲区大小的期望值,还取决于正常的系统利用率。
典型地,分时系统给D选择了4K字节到8K字节之间的一个值。
四、变量的定义:
1.结构体变量的定义:
a.首部变量:
//IP头部,总长度20字节
typedefstruct_ip_hdr
{
#ifLITTLE_ENDIAN
unsignedcharihl:
4;//首部长度
unsignedcharversion:
4,//版本
#else
unsignedcharversion:
4,//版本
unsignedcharihl:
4;//首部长度
#endif
unsignedchartos;//服务类型
unsignedshorttot_len;//总长度
unsignedshortid;//标志
unsignedshortfrag_off;//分片偏移
unsignedcharttl;//生存时间
unsignedcharprotocol;//协议
b、分片变量:
intip_fragment(structsk_buff*skb,int(*output)(structsk_buff*))
{
structiphdr*iph;
unsignedchar*raw;
unsignedchar*ptr;
structnet_device*dev;
structsk_buff*skb2;
unsignedintmtu,hlen,left,len;
intoffset;
intnot_last_frag;
structrtable*rt=(structrtable*)skb->dst;
interr=0;
};
c、校验和变量:
unsignedshortchecksum(unsignedshort*buf,intnword)
{
unsignedlongsum;
for(sum=0;nword>0;nword--)
sum+=*buf++;
sum=(sum>>16)+(sum&0xffff);
sum+=(sum>>16);
return~sum;
}
d:
队列变量:
#dedineBUFFER_SIZE65535
Charbuffer[BUFFER_SIZE];//设置缓冲区
While(true)
{recv(sock,buffer,BUFFER_SIZE,0);//j接收数据包
……..
2、自然函数的处理过程
a、整体封装
1)使用套接字
原始套接字套接字分为三种,即流套接字(StreamSocket)、数据报套接字(DatagramSocket)和原始套接字(RawSocket)。
要进行IP数据包的接受与发送,应使用原始套接字。
创建原始套接字的代码如下:
SOCKETsock;
Sock=WSASoccet(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERRLAPPED);
在WSASoccet函数中,第一个参数指定通信发生的区字段,AF_INET是针对Internet的,允许在远程主机之间通信。
第二个参数是套接字的类型,AF_INET地址族下,有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW三种套接字类型。
在这里,我们设置为SOCK_RAW,表示我们声明的是一个原始套接字类型。
第三个参数依赖于第二个参数,用于指定套接字所用的特定协议,这里使用IP协议。
第四个参数为WSAPROTOCOL_INFO位,该位可以置空,永远置0。
第六个参数是标志位,WSA_FLAG_OVERRLAPPED表明可以使用发送接收超时设置,本课程设计也可以把这个标志位设置为NULL,因为本设计不用考虑超时情况。
创建原始套接字后,IP头就会包含在接收的数据中。
然后,我们可以设置IP头操作选项,调用sotscockpot函数。
其中flag设置为TRUE,并设定IP_HDRINCL选项,表明用户可以亲自对IP头进行处理。
BOOLflag=true;
setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag));
之后,使用如下代码完成对socket的初始化工作
/*获取主机名*/
charhostname[128];
gethostname(hostname,100);
/*获取IP地址*/
hostent*pHostIP;
pHostIP=gethostbyname(hostname);
/*填充SOCKADDR_IN的结构内容*/
sockaddr_inaddr_in;
addr_in.sin_addr=*(in_addr*)pHostIP->h_addr_list[0];
addr_in.sin_family=AF_TNET;
addr-in.sin_port=htons(6000);
/*绑定socket*/
bind(sock,(POSCKADDR)&addr_in,sizeof(addr_in));
填写sockaddr_in的内容时,其地址值应填写为本机IP地址可以通过gethostbyname()函数获取;端口号可以随便填写,但不能与系统冲突;协议族应填写为AF_INET。
注意,sockaddr_in结构的值必须是以网络字节顺序表示的值,而不能直接使用本机字节顺序的值,使用htoms()函数可以将无符号短整型的主机数据转换为网络字节的顺序的数据。
最后使用bind()函数将socket绑定到本地网卡上。
绑定网卡后,需要WSAIoctl()函数把网卡设置为混杂模式,使网卡能够接收所有网络数据,其关键代码如下:
#defineSIO_RCVALL_WSAIOW(IOC_VENDOR,1)
DWORDdwBufferLen[10];
DWORDdwBufferInLen=1;
DWORDdwBytesReturned=0;
WSAIoctl(SnifferSocket,IO-RCVALL,&dwBufferInLen,sizeof(dwBufferInLen),&dwBufferLen,Sizeof(dwBufferLen),&dwByteReturned,NULL,NULL);
如果接收的数据包中的协议类型和定义的原始套接字匹配,那么接收到的数据就拷贝到套接字中。
因此,网卡就可以接收所有经过的IP包。
2)接收数据包
在程序中可使用RECV()函数接收经过的IP包。
该函数有四个参数,第一个参数接收操作所用的套接字描述符;第二个参数接收缓冲区的地址;第三个参数接收缓冲区的大小,也就是所要接收的字节数;第四个参数是一个附加标志,如果对所发送的数据没特殊要求,直接设为0。
因为IP数据包的最大长度是65536B,因此缓冲区的大小不能小于65535B。
设置缓冲区后,可利用循环来反复监听接收IP包,用recv()函数接收功能的代码如下:
#dedineBUFFER_SIZE65535
Charbuffer[BUFFER_SIZE];//设置缓冲区
While(true)
{recv(sock,buffer,BUFFER_SIZE,0);//j接收数据包
……..
net.ipv4.ipfrag_low_thresh=196608
net.ipv4.ipfrag_high_thresh=262144
......
b、队列处理
当分片所用的内存超过一定的上限时(sysctl_ipfrag_high_thresh)会调用ip_evicator以释放内存。
ip_evicator会找寻可清空的IPQ,并将其清空,直到到达到可用的下限(sysctl_ipfrag_low_thresh)。
这个值在ip_fragment.c中按如下定义:
intsysctl_ipfrag_high_thresh=256*1024;
intsysctl_ipfrag_low_thresh=192*1024;
同样,用sysctl-a可可看到这两参数,同时可以动态修改。
sysctl-a
......
net.ipv4.ipfrag_low_thresh=196608
net.ipv4.ipfrag_high_thresh=262144
......
理论上ip_evicator应该采用LRU算法,将最古老的IPQ清除。
Memorylimitingonfragments.Evictortrashes(丢弃)theoldest*fragmentqueueuntilwearebackunderthelowthreshold.
Ip_evictor函数遍历分片队列,同时丢弃到目前为止已经收集到的分片,直到所使用的总的内存量小于规定的限制时为止。
只要占用的内存大于对他的内存限制值,这个函数就调用Ip_free函数。
当分片队列为空并且内存阀值也超过时,Ip_evictor函数可以引起内核的恐慌。
LRU算法,全局变量ipq_hash[64]链表,越靠近链尾越老引用计数越大越不容易被洗掉
两重循环每次洗掉时间最老引用计数最少的分片,直到总占用内存降到sysctl_ipfrag_low_thresh=192*1024。
因为IP数据包的最大长度是65536B,因此缓冲区的大小不能小于65535B。
设置缓冲区后,可利用循环来反复监听接收IP包,用recv()函数接收功能的代码如下:
#dedineBUFFER_SIZE65535
Charbuffer[BUFFER_SIZE];//设置缓冲区
While(true)
{recv(sock,buffer,BUFFER_SIZE,0);//j接收数据包
…….
.
五、设计流程图
1、
数据包的整体封装设计流程图
N
Y
2、
队列流程图:
Y
N
Y
N
Y
六.心得体会
在此次的TCP/IP课程设计中,我们四个人一组花了近一个周的时间,通过翻阅资料以及上网搜索相关资料,终于完成了TCP/IP的课程设计。
我们四个人每个人都有自己相应的负责模块,每个人在在各自的模块的领域里认认真真的动手去做。
四个人在一起经过多次的讨论和修改,最终完结。
所以在这次的课程设计中,动手能力得到了很大的提高,而且将这学期所学的网络的知识和以前所学的编程的知识充分的联系起来,对这门课的认识又提高了一层。
不过在这次课程设计中,我们还学到了另一种知识,要学会团结,团结就是力量!
七、参考文献
1.TCP/IP详解 卷2:
实现(美)莱特等著机械工业出版社
2.TCP/IP详解 卷1:
协议(美)史蒂文斯著机械工业出版社
3.用TCP/IP进行网际互连第二卷(美)DouglasE.Comer著电子工业出版社
附录程序
#include"stdafx.h"
#include"winsock2.h"
#include"ws2tcpip.h"
#include"stdio.h"
typedefstruct_IP_HEADER
{
union
{
BYTEVersion;
BYTEHdrLen;
};
BYTEServiceType;
WORDTotalLen;
WORDID;
union
{
WORDFlags;
WORDFragoff;
};
BYTETimeToLive;
BYTEProtocol;
WORDHdrChksum;
DWORDSrcAddr;
DWORDDstAddr;
BYTEOptions;
}IP_HEADER;
voidgetVersion(BYTEb,BYTE&version)
{
version=b>>4;
}
voidgetIHL(BYTEb,BYTE&result)
{
result=(b&0x0f)*4;
}
char*parseServiceType_getProcedence(BYTEb)
{
switch(b>>5)
{
case7:
return"NetworkControl";
break;
case6:
return"InternetworkControl";
break;
case5:
return"CRITIC/ECP";
break;
case4:
return"FlashOverride";
break;
case3:
return"Falsh";
break;
case2:
return"Immediate";
break;
case1:
return"Priority";
break;
case0:
return"Routine";
break;
default:
return"Unknown"
}
}
char*parseServiceType_getTOS(BYTEb)
{
b=(b>>1)&0x0f;
switch(b)
{
case0:
return"Normalservice";
break;
case1:
return"Minimizemonetarycost";
break;
case2:
return"Maximizereliability";
break;
case4:
return"Maximizethroughput";
break;
case8:
return"Minimizedelay";
break;
case15:
return"Maximizesecurity";
break;
default:
return"Unknown";
}
}
voidgetFlags(WORDw,BYTE&DF,BYTE&MF)
{
DF=(w>>14)&0x01;
MF=(w>>13)&0x01;
}
voidgetFragoff(WORDw,WORD&fragoff)
{
fragoff=w&0x1ffff;
}
char*getProtocol(BYTEProtocol)
{
switch(Protocol)
{
case1:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- IP 数据 封装 过程 设计