关于tcp,udp,ip协议的另类详解
我又要讲故事了不想听的跳过。。。最近在面试一些I做通信的公司,为啥要面这些企业呢,因为两个原因:第一我是应用工程师想要扩展技术面就得向下,向上发展,向下就是linux的内核和驱动,向上就是网络,我做过一点底层,但是想要深入还需要一点时间,而且由于行业原因底层的开发比较困难。第二个是因为我的网络这块很弱。
下面引入正题。
协议说明
分层
说起网络的协议其实我们学习的都是iso的网络七层协议,但是事实上互联网主要的协议是tcp/ip协议,这是因为iso在指定协议标准时比较晚,那时tcp/ip已经大部分应用与互联网,所以主要用tcp/ip协议。如果想要了解iso的七层协议可以自己读相关课程,这里我不多做详解。
在接收时请从物理层看起,它是一个解包的过程;发送时从应用开始,它是一个创建包过程。
层名称 | 发送 | 接收 |
---|---|---|
物理层 | 物理传输 | 物理传输 |
数据链路层 | 相邻节点流量控制,数据分片,crc校验,加mac | crc校验,去帧头,组合数据 |
网络层 | 数据路由,加ip | 去ip |
传输层 | 端到端流量控制,校验和,加端口号 | 数据组合 |
会话层 | 连接控制 | 连接控制 |
表示层 | 对数据加密,压缩 | 解密解压缩 |
应用层 | 把用户数据写入发送buf | 获取数据 |
事实上tcp/ip只有四层协议,将iso的物理和链路合并成网络接口层,会话,表示,应用合并成应用层。
层名称 | 发送 | 接收 |
---|---|---|
网络接口层 | 相邻节点流量控制,数据分片,crc校验,加mac,物理传输 | crc校验,去帧头,组合数据,物理传输 |
网络层 | 数据路由,加ip | 去ip |
传输层 | 端到端流量控制,校验和,加端口号 | 数据组合 |
应用层 | 对数据加密,压缩,连接控制,把用户数据写入发送buf | 解密解压缩,连接控制,获取数据 |
我们再来看下协议的报文
报文说明
总体的报文图
我们先看链路层的帧格式
展开后
Ethernet帧头为 14字节:
首先是目的MAC 6个字节,然后源MAC6个字节,接下来数据类型两个字节。 常见的类型如下
类型 | 值 |
---|---|
IPv4 | 0x0800 |
ARP | 0x0806 |
PPPoE | 0x8864 |
802.1Q tag | 0x8100 |
IPV6 | 0x86DD |
MPLS Label | 0x8847 |
FCS为 4字节:Frame check sequence,校验序列
ip报文
ip报一般头部为20个字节
分段名 | 大小 | 说明 |
---|---|---|
版本号(Version) | 4bit | 表明IP协议的版本号。一般为0100(IPv4),0110(IPv6) |
IP包头长度(Header Length) | 4bit | 用于描述IP包头长度,因为IP包头长度是可变的,以4个字节为一个单位。例如,一个IP包头的长度最长为“1111”,即15*4=60个字节。IP包头最小长度为20字节。 |
服务类型(Type of Service) | 8bit | 其中前3比特为优先权子字段(Precedence,现已被忽略)。第8比特保留未用。第4至第7比特分别代表延迟、吞吐量、可靠性和花费。当它们取值为1时分别代表要求最小时延、最大吞吐量、最高可靠性和最小费用。这4比特的服务类型中只能置其中1比特为1。可以全为0,若全为0则表示一般服务。服务类型字段声明了数据报被网络系统传输时可以被怎样处理。例如:TELNET协议可能要求有最小的延迟,FTP协议(数据)可能要求有最大吞吐量,SNMP协议可能要求有最高可靠性,NNTP(Network News Transfer Protocol,网络新闻传输协议)可能要求最小费用,而ICMP协议可能无特殊要求(4比特全为0)。实际上,大部分主机会忽略这个字段,但一些动态路由协议如OSPF(Open Shortest Path First Protocol)、IS-IS(Intermediate System to Intermediate System Protocol)可以根据这些字段的值进行路由决策。 |
IP包总长(Total Length) | 16bit | 以字节为单位计算的IP包的长度 (包括头部和数据),所以IP包最大长度65535字节 |
标识符(Identifier) | 16bit | 该字段和Flags和Fragment Offest字段联合使用,对较大的上层数据包进行分段(fragment)操作。路由器将一个包拆分后,所有拆分开的小包被标记相同的值,以便目的端设备能够区分哪个包属于被拆分开的包的一部分 |
标记(Flags) | 3bit | 第一位是保留位不使用。第二位是DF(Don’t Fragment)位,DF位设为1时表明路由器不能对该数据包分包。如果一个数据包无法在不分段的情况下发送,则路由器会丢弃该数据包并返回一个错误信息。第三位是MF(More Fragments)位,当路由器对一个上层数据包分段,则路由器会在除了最后一个分段的IP包的包头中将MF位设为1 |
片偏移(Fragment Offset) | 13bit | 表示该IP包在该组分片包中位置,接收端靠此来组装还原IP包 |
生存时间(TTL) | 8bit | 当IP包在网络上传送时,每经过一个路由器,TTL就自动减一。值为0时,则丢弃报文。防止报文进入环路 |
协议(Protocol) | 8bit | 标识IP头后面的报文协议类型以下是比较常用的协议号:ICMP(1),IGMP(2),TCP(6),UDP(17), IGRP(88),OSPF(89) |
头校验和(Header Checksum) | 16bit | 用来做IP头部的正确性检测,但不包含数据部分。由于路由器会改变TTL,所以路由器会为每个通过的数据包重新计算这个值 |
源和目的地址(Source and Destination Addresses) | 32bit | 标识了这个IP包的起源和目标地址。要注意除非使用NAT,否则整个传输的过程中,这两个地址不会改变 |
tcp报文
报文头
tcp段一般头部有20个字节表示
分段名 | 大小 | 说明 |
---|---|---|
源端口号(Source Port) | 16bit | 指明发送数据的进程 |
目的端口号(Destination Port) | 16bit | 指明目的主机接收数据的进程 |
序号(Sequence Number) | 32bit | 序号用来标识从TCP发送端向接入端发送的数据字节流进行编号,可以理解成对字节流的计数,一个tcp流的初始***(ISN)并不是从0开始的,而是采用一定的随机算法产生的,因此ISN可能很大(比如(2^32-10)),因此同一个tcp流的seq号可能会回绕到0。而我们tcp对于丢包和乱序等问题的判断都是依赖于***大小比较的。此时就出现了所谓的tcp***回绕(sequence wraparound)问题 |
确认号(Acknowledgement Number) | 32bit | 确认号包含发送确认的一端所期望收到的下一个序号。确认号只有在ACK标志为1时才有效,也就是说,在tcp通讯时ACK保持为1 |
首部长度 | 4bit | 用于表示TCP报文首部的长度。一个TCP报文前20个字节是必有的,后40个字节根据情况可能有可能没有。单位为4字节,如果TCP报文首部是20个字节,则该位应是20/4=5。 |
保留位(Reserved) | 6bit | 必须是0,它是为将来定义新用途保留的 |
标志(Code Bits) | 6bit | 在TCP报文中不管是握手还是挥手还是传数据等,这6位标志都很重要。URG:紧急标志位,说明紧急指针有效;ACK:确认标志位,多数情况下空,说明确认序号有效;PSH:推标志位,置位时表示接收方应立即请求将报文交给应用层;RST:复位标志,用于重建一个已经混乱的连接;SYN:同步标志,该标志仅在三次握手建立TCP连接时有效;FIN:结束标志,带该标志位的数据包用于结束一个TCP会话 |
窗口大小(Window Size) | 16bit | TCP流量控制由连接的每一端通过声明的窗口大小来提供 |
检验和(Checksum) | 16bit | 该字段覆盖整个TCP报文端,是个强制性的字段,是由发送端计算和存储,到接收端后,由接收端进行验证 |
紧急指针(Urgent Pointer) | 16bit | 指向数据中优先部分的最后一个字节,通知接收方紧急数据的长度,该字段在URG标志置位时有效 |
选项(Options) | 32bit | 必须以4B为单位变化,必要时可以填充0。通常包含:最长报文大小(MaximumSegment Size,MSS)、窗口扩大选项、时间戳选项、选择性确认(Selective ACKnowlegement,SACK)等 |
udp报文
报文头
UDP数据报由首部和数据两部分组成,其中首部只有8字节。
分段名 | 大小 | 说明 |
---|---|---|
源端口号(Source Port) | 16bit | 指明发送数据的进程 |
目的端口号(Destination Port) | 16bit | 指明目的主机接收数据的进程 |
长度 | 16bit | 报头和数据两部分的总字节数 |
检验和(Checksum) | 16bit | UDP检验和作用于UDP报头和UDP数据的所有位。由发送端计算和存储,由接收端校验 |
目的端口号(Destination Port) | 16bit | 指明目的主机接收数据的进程 |
下面说一写实际的问题
1.数据如何发送
1.1.0 tcp的数据下发方式:
A:数据在应用层,主要对数据进行加密,压缩,确认连接状态主要是会话层的操作,这里简单介绍一下加密的公密和私密加密方式RSA加密,核心原理就是,用公密加密的密文只能用对应的私密解密,用私密加密的密文只能用公密解密。
例如:小明想写一个加密的信件给小红,小明可以使用小红的公密加密,然后小红拿到密文用自己的私密解密就好。但是实际的应用过程中,如果小绿模仿小明用小红的公密给小红发数据,那小红就不知道什么才是真正小明发的,那么就需要在数据中加上小明的名字,所以,小明先把自己的名字用自己的私密加密,然后再把组合的内容用小红的公密加密,这样小红拿到密文,先用自己的私密解密,知道内容再用小明的公密解密,知道谁发的。
B:数据到达传输层,当数据超过MTU(最大包)时,传输层对数据进行分片,产生不同序号(Sequence Number)的数据报,每个数据报大小不超过1480字节,这个是在三次握手的前2次服务器和客户机通过tcp报文的选项(Options)的MMS确认的,一般为536字节。当然选项(Options)分段还可以在ping的时候的ICMP加时间戳等信息。对分片的每一个报文加上TCP头,下发。这里会有一个疑问,seq是32bit,最大编号为4G,那么传输大于4G的数据要如何处理,这里就涉及到序号的回绕机制,每个序号都是代表上一次序号加上上一次发送数据的和(seq=前一个seq+前一个数据长度),当加到4G是自动回绕到0开始加。这样就产生了流机制,所以tcp的数据包大小没有限制,像数据流。我们在上报中说明数据复原组合的逻辑。
C:到网络层,下发的数据报在ip层加上ip报文头
D:到链路层,加上链路层协议,产生数据帧传输
1.1.1 tcp的数据上报方式:
A:到链路层,提取链路层数据,产生ip报文上报网络层
B:到网络层,上报的数据报,去除ip报文头
C:数据到达传输层,需要对数据进行组合,根据序号,组织数据,对数据进行排序,以及出错重发。这里就涉及2块,一个是从发机制,一个是组织机制。在tcp协议中是有滑动窗口这个概念的,也就是说,在报文发出后会备份到滑动窗口,然后继续下发下一个报文,如果收到应答ACK,就把滑动窗口的备份清掉,如果获得NAK就是出错应答,就会把数据包从发。那么这里会出现的问题就是如果序号超过4G,这样就有2个同样序号的数据在滑动窗口,或者滑动窗口满了,如何处理。第一滑动窗口不会存2个序号相同的报文,因为一个16位,一个32位。当滑动窗口满就会阻塞,并且在数据报中有超时机制,当超过时间未回复就会自动清除。在传输层数据就被通过序号给组织起来了。
D:数据在应用层,主要对数据进行解密,解压缩压缩。
1.2.0 udp的数据下发方式:
A:数据在应用层基本和tcp一样,但是数据大小有要求
B:数据到达传输层,传输层指明了数据包的大小为65535=64k,也就是说udp每次只能穿最大64k数据。
C:到网络层,由于MTU的限制,最大不超过1500,所以会对udp包进行分片,在标识加上序号表明当前是报文的第几个帧编号。
D:到链路层,加上链路层协议,产生数据帧传输
1.2.1 udp的数据上报方式:
A:到链路层,提取链路层数据,产生ip报文上报网络层
B:到网络层,根据标识和偏移对数据进行组合,如果标识丢失,则整个数据报丢失
C:数据到达传输层,上报,去除协议头。
D:数据在应用层,主要对数据进行解密,解压缩压缩。
补充:
tcp协议是在传输层分包,是在目标和源之间的,其中有滑动窗口,所以说是类似数据流的,并且无数据长度限制。并且tcp经过三次握手,使得数据有专门的传输路径。
udp协议是在网络层分包,在传输层确认了数据段的最大大小,是点对点的当时,所以并且无连接,数据可能丢失,并且路径可以不同。
2.优化数据发送
1.硬件环境:带宽
2.应用层处理:压缩减少数据量,对大数据进行应用层分割重组然后多路连接
2.协议修改:tcp协议的窗口拓展,选择性确认,修改MMS