努力经营当下,直至未来明朗!
文章目录
- 前言
- 传输层
- 1. 介绍UDP协议
- 2.【TCP】(重难考点)
- TCP可靠传输的机制
- 1. 确认应答
- 2. 超时重传
- 3. 连接管理(三次握手、四次挥手)【面试题!!】
- THINK
前言
一个人最大的痛苦来源于对自己无能的痛苦!
Hi,这里是不想秃头的宝贝儿
本文主要介绍网络原理中的【传输层】,但是传输层内容很多也很重要,所以要分为好几部分进行介绍。
【传输层】中主要是UDP和TCP,其中就会涉及到比较多的面试题。
传输层
- 传输层是端到端之间的传输,重点关注的是起点和终点。
- 核心协议:
① UDP:无连接、不可靠传输、面向数据报、全双工
② TCP:有链接、可靠传输、面向字节流、全双工
1. 介绍UDP协议
- 所谓的学习协议,其实很大的工作就是在理解协议的报文格式。
- UDP协议格式(来自于教科书):
实际格式:
① 注:端口号是0~65535 =》 在传输层协议中,表示端口号的长度就是2字节,即16位。
② UDP长度是2字节,2字节能表示的范围是0~ 65535,也就是0~64kb。即:一个UDP报文最长是64kb。
③ 所以:如果需要使用UDP传输一个比较大的数据就需要考虑进行拆包。【拆包就是把一个大的数据拆成多个小的】
① 在应用层代码这里,针对数据进行拆包,拆成多个UDP数据报分别传输:开发和测试都比较复杂,风险较高,可能存在到达顺序混乱以及丢包问题;
② 所以:直接使用TCP:TCP是字节流的,对于包的长度是没有限制的
校验和:UDP的校验和使用的是比较常见的CRC算法(循环冗余校验):把UDP中的每个字节都进行累加,加和放到一个两个字节的数字中,加的过程如果溢出了也没关系。发送方发送的时候计算一个校验和放到UDP报头中,然后接收方按照同样的规则再计算一遍校验和来检验和报头的校验和是否相等。(其实也会存在多个比特位改变而恰好校验相等的情况,但是概率极低,所以一般认为只要校验和相等就是正确的数据
① 16位UDP长度,表示整个数据报(UDP首部+UDP数据)的最大长度;
② 如果校验和出错,就会直接丢弃。
③ 应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
- UDP只有接收缓冲区,没有发送缓冲区:
① UDP没有真正意义上的 发送缓冲区。发送的数据会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作;
② UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的UDP报的顺序和发送UDP报的顺序一 致;如果缓冲区满了,再到达的UDP数据就会被丢弃。
- UDP的socket既能读,也能写,这个概念叫做 全双工。
- 基于UDP的应用层协议(简单了解,没时间不看)
NFS:网络文件系统
TFTP:简单文件传输协议
DHCP:动态主机配置协议
BOOTP:启动协议(用于无盘设备启动)
DNS:域名解析协议
当然,也包括你自己写UDP程序时自定义的应用层协议
2.【TCP】(重难考点)
(谈到计网,关于TCP的问题就是最高频的问题)
- TCP特点:有连接、可靠传输、面向字节流、全双工
- TCP协议段格式:
① 4位首部长度只是描述TCP报头有多长,4个比特位能够表示的范围0~15,但是这里的单位是4字节,也就是说如此处的15表示报头的长度其实是【15*4=60字节】
② 选项部分可有可无,可以有一个选项,也可以有多个选项【所以,这里就是TCP报头可变的原因】
③ 【TCP报头的前20个字节是固定的,后面的选项可变,选项可以是0字节,最多是40字节】
④ 保留位:现在虽然不用,但是先占个位置,留下可扩展的空间
⑤ 6个特殊标志位
URG:紧急指针是否有效
ACK:确认号是否有效
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段
SYN:请求建立连接;我们把携带SYN标识的称为同步报文段
FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段
- 作为传输层协议,协议报头中是必须要明确源端口和目的端口的。
- TCP基本特性中的 面向字节流、有连接、全双工 在代码中都是可以体现出来的,但是可靠传输在代码中体现不出来。而**【可靠传输】是TCP中最核心的特性!**
- 【可靠传输:指的是数据传输过去之后,发送方能够知道自己是发送成功还是没成功】
TCP可靠传输的机制
1. 确认应答
- 采用的是【应答机制】,回复的报文就称为“应答报文”,也称“ACK报文”(acknowledge)。体现在特殊标志位中,普通报文ACK这一位为0,应答报文ACK这一位为1。
- 【确认应答机制】就是TCP保证可靠性的最核心机制!
(网上有些资料所说的TCP的可靠性是通过“三次握手四次挥手”来保证的,这是错误的!) - 网络通信会存在“后发先至”情况:网络上通信传输的路径是复杂的,两点之间两个报文可能会走不一样的路线。
而“后发先至”是网络的基本结构导致的,是无法避免的,所以只能自己想办法让含义不被误会,故解决方案:针对请求和应答报文进行编号。也就是说:在确认应答机制中引入序号来保证不出现歧义。
32位序号:针对请求数据进行编号;
32位确认序号:只是针对ACK报文有效
-
TCP是一个字节流的协议,编号的时候也是以字节为单位进行编号的。(不是简单的按顺序编号)
-
确认应答机制(编号重点理解一下)
-
序号在理论上是会溢出的,但是不太影响,32位序号与确认序号相当于4GB,就算数据很多溢出了,大不了就到头之后重新计算就行。
-
确认应答描述的是 数据包顺利到达对方且对方给出响应,但是在传输过程中可能会丢包,如果丢包又该如何呢?
① 【丢包的原因:网络环境非常复杂,且交换机的转发能力是有上限的,如果数据报庞大的情况导致交换机的转发达到上限,此时就无法快捷的完成转发了,就可能会导致一部分数据报超时。】
② 如果数据丢包了,此时就需要考虑通过“超时重传”来进行了。
2. 超时重传
-
在丢包的情况下, 如何进行【超时重传】呢?
① 如果是发送方数据丢了,就进行正常超时重传
② 如果是ACK应答报文丢了,则实际操作是发送方发的消息也需要再次发送,此时因为丢失ACK就会导致接收方收到重复信息,但是这明显不是最妥善的处理方式;所以TCP就会针对相同的消息进行去重(根据序号来去重就行),保证了应用层代码通过socket读取数据的时候读到的不是重复数据。 -
那么超时时间如何确定?
一般系统里会有一个配置项来描述超时时间的阈值,但是实际的超时时间是不确定的。
例如,第一次出现丢包时,发送方就会在达到超时时间阈值之后进行重传;如果重传的数据仍然无响应,那么还会继续进行超时重传,但是第二次超时时间一般要比第一次更长,也就是超时时间并不是均等的,而是逐渐变大的。
【超时时间逐渐变大的理由】:如果单个数据报丢包的概率较小,此时由概率论计算可知第二次传输大概率是可以顺利到达的;如果第二次传输也没有到达的话,一般就说明当前环境比较糟糕,此时单个数据报丢包的概率就非常大了,如此就算传输再频繁也是无济于事的,倒不如降低传输频率以节省主机开销。
这样的重传如果在重试几次之后依旧无法传输,就会尝试重置TCP连接(也就是:断开重连);此时如果还是连不上就直接释放连接(彻底放弃连接)。
3. 连接管理(三次握手、四次挥手)【面试题!!】
-
【连接管理】:描述的是TCP建立连接和断开连接的过程。
-
连接:TCP的连接是逻辑上的“虚拟连接”
如:主机A和主机B建立连接实际上是在其各自的系统内核中记录一个数据结构,里面包含了连接的对方的信息,如IP、端口、使用的协议等等。 -
建立连接:双方建立一个相互认同的关系
【三次握手流程非常重要,面试必考!!】
使用【三次握手】:其实建立连接的过程是四次数据的交互。
①主机A向主机B申请,尝试建立连接 :syn(同步报文段)
②主机B给A回应 :ack
③主机B向A申请,尝试建立连接 : syn
④主机A给B回应 :ack
(但是说三次握手是因为②③可以合并为一条消息)
【syn也是在特殊标记位中,syn这一位如果为1就说明这是一个同步报文段,尝试与对方建立连接】
(面试必考!!)
① 谈到数据结构,最高频的是链表;
② 谈到操作系统,最高频的是进程和线程;
③ 谈到网络,最高频的是TCP,尤其是三次握手!
-
为啥要建立连接?建立连接的意义是啥?
① 投石问路:检查一下当前的网络状况是否畅通。(三次握手建立连接其实并不传输任何业务信息)
② 三次握手同时也是在检查通信双方的发送能力和接收能力(两次是不行的,测试不完整)
③ 三次握手过程中,也在协商一些重要的参数。如TCP序号并不是从1开始的,通常是在建立连接的时候协商的数字,如果连接断开又快速重连,接收方就可以区分当前收到的数据是上个连接还是当前连接。 -
【两个重点的TCP状态:(建立连接)】
① LISTEN:服务器启动且绑定端口之后(new ServerSccket完成),相当于手机开机、信号良好,别人可以进行打电话。
② ESTABLISHED:连接建立好之后的稳定状态,相当于拨通电话之后可以进行说话交流了。 -
断开连接:双方取消互相的认同关系
【四次挥手:通信双方各自向对方申请断开连接,再各自给对方回应】
① 主机A给主机B发送申请断开连接的请求:FIN——FIN在特殊标记位中存在,该位为1就表示申请断开与对方的连接
② 主机B给A发送确认收到ACK
③ 主机B给A同样发送申请与对方断开连接的请求:FIN
④ 主机A给B发送确认信息ACK
(②和③在“三次握手”中100%能够合并,但是在“四次挥手”中是有可能会合并)
-
在“三次握手”中,主机B给主机A返回确认ACK以及申请连接SYN都是由内核触发的,时机完全相同,操作系统就会把两个包合并成一个
(为啥不能是“四次握手”:可以但没必要,白白浪费时间) -
在“四次挥手”中,ACK和FIN的触发时机是不相同的,ACK是由操作系统内核收到主机A给B发送的FIN之后立即触发的,而主机B给A发送FIN是应用程序显示的调用socket的close方法触发的。
-
既然在“四次挥手”过程中两个数据时机不相同,为啥还有可能合并呢?
TCP里有一个机制:捎带应答(后面细讲) -
两个重要的TCP状态(断开连接):
① CLOSE_WAIT:等待代码中调用close操作。(如果服务器上出现大量的CLOSE_WAIT状态的连接,说明服务器代码bug,close没有被及时调用到)
② TIME_WAIT:返回ACK的一方会进入TIME_WAIT。
如:主机A在处理完上一个ACK之后不能立即释放连接,而是需要保持一定时间,这是为了万一最后的ACK丢了,还有机会进行重传。(也就是说:如果A给B发送确认ACK的时候ACK丢包了,那么此时B就需要给A重新发送FIN,此时A处的TIME_WAIT就是非常必要的,如果A在等了一段时间之后没有FIN重传过来就认为ACK顺利到达了)
- MSL:网络上两个位置之间传输数据消耗的最大时间,所以TIME_WAIT只需要等待2MSL就行
注:保证TCP可靠性还有很多机制,下一篇博客接着讲这些机制。
THINK
- UDP、TCP特点以及协议格式
- 【重点】TCP的可靠传输的保证机制(这里介绍了3个)
- 确认应答、超时重传、连接管理
- 其中三次握手、四次挥手重点!!!