本文主要分析运输层的两种协议TCP和UDP,重点在于TCP如何实现可靠传输,并且进行流量控制,以及TCP的三次握手和四次挥手的详细过程。最后对TCP和TDP的两种协议进行了比较。
主要内容:
- 运输层的认识
- UDP的认识
- TCP认识
- UDP和TCP的区别
运输层就是位于应用层和网络层之间的,为运行在不同主机上的应用进程提供直接的通信服务是运输层的任务。 物理层、数据链路层以及网络层他们共同解决了将主机通过异构网络互连起来所面临的问题,实现了主机到主机的通信,而通信的真正实体是位于通信两端主机中的进程。
因特网的运输层为应用层提供了两种不同的运输协议,即面向连接的TCP和无连接的UDP UDP是无连接的,不可靠的运输协议,TCP是面向连接的,可靠的运输协议
运输层在网络通信中的作用:
运输层在网络通信中作用过程:
- 进程Ap1与Ap4之间进行基于网络的通信,进程Ap2与Ap3之间进行基于网络的通信
- 在运输层使用不同的端口,来对应不同的应用进程
- 然后通过网络层及其下层来传输应用层报文
- 接收方的运输层通过不同的端口,将收到的应用层报文,交付给应用层中相应的应用进程
注:这里所说的主机和主机之间的通信其实是主机进程之间的通信
C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
2、用户数据报协议UDP2.1 介绍
用户数据报协议(User Datagram Protocol),是TCP/IP体系结构运输层中的一个重要协议,这种逻辑通信信道是一条不可靠信道。 特点:
- 是无连接的协议,提供无连接服务
- UDP 传送的数据单位协议是 UDP 报文或用户数据报。
- 支持单播、多播、广播
- 不提供可靠交付
- 不需要套接字(Socket)
2.2 运输过程
说明:
- UDP报文是面向应用报文的,因此UDP对应用进程交下来的报文既不合并也不拆分,而是保留这些报文的边界
- UDP报文以报文为单位进行发送和接收
3.1 介绍
TCP 是TCP/IP体系结构运输层中的重要协议,当运输层采用面向连接的 TCP 协议时,尽管下面的网络是不可靠的(只提供尽最大努力服务),但这种逻辑通信信道就相当于一条全双工的可靠信道。 TCP 传送的数据单位协议是 TCP 报文段(segment)
特点:
- 面向连接的协议,提供面向连接服务,TCP之间的通信必须要在两个套接字(Socket)之间建立连接
- 其传送的运输协议数据单元TPDU是TCP报文
- 仅支持点对点单播,不支持多播和广播
- 提供可靠服务
- TCP是面向字节流的,这正是TCP实现可靠传输、流量控制、以及拥塞控制的基础
TCP传输过程
说明: 发送方:
- TCP会把应用进程交付下来的数据块看作是一连串无结构的字节流,TCP并不知道这些待传送的字节流的含义
- TCP将相应的字节流进行编号,并存储在自己发送缓存中
- TCP会根据发送策略,提取一定量的字节构建TCP报文并发送
接收方:
- 一方面从所接受到的TCP报文段中,取出数据载荷部分并存储在接收缓存中;一方面将接收缓存中的一些字节交付给应用进程
- 接收方的应用进程必须有能力识别收到的字节流,把它还原成有意义的应用层数据
C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
3.2 超时重传3.2.1 介绍
在TCP传输中为了实现可靠传输和流量控制都需要涉及超时重传,超时重传中最为重要的是计算超时重传的时间。 RTO是超时重传时间,RTT是往返时间。
超时重传时间不能远大于往返时间,会浪费资源
超时重传时间不能小于往返时间,会造成不必要的重传
超时重传时间应当略大于往返时间,为了避免误差,应当选用一段时间内的加权的往返时间
总结: 1、如果超时重传时间RTO的值设置得比RTT的值小很多,这会引起报文段不必要的重传,使网络负荷增大 2、如果超时重传时间RTO的值设置得远大于RTT0的值,这会使重传时间推迟的太长,使网络的空闲时间增大,降低传输效率 3、因此需要将超时重传时间设置的略大于一次往返时间。
3.2.3 超时重传时间RTO的计算 超时重传时间的要略大于一次往返时间,但一次往返时间是不固定的,因此超时重传时间的计算是基于加权平均往返时间
说明:
- 这是RFC6298建议使用下式计算超时重传时间RTO
- 算法本身不再说明,只要知道是根据加权平均往返时间计算的
3.2.4 往返时间RTT的测量 往返时间RTT的测量不能简单的进行一次往返时间的计算,有如下问题需要处理
问题1:如果报文丢失或确认报文的迟到,都会导致重传报文。这样两次的报文发送使得无法准确计算一次往返时间。
- 超时重传时,有两个发送报文,一个确认报文,如果以第一个发送的报文来计算就会偏大
- 如果在超时重传中,确认报文是第一个报文的确认报文,若当做重传报文的确认来计算,就会偏小
解决1:Karn算法
- 在计算加权平均往返时间RTTs时,只要报文段重传了,就不采用其往返时间RTT样本。
问题2: 对于问题1的解决会引入新问题
- 设想这样的情景:报文段的时延突然增大了很多,并且之后很长一段时间都会保持这种时延。
- 因此在原来得出的重传时间内,不会收到确认报文段,于是进行超时重传
- 而通过Karn算法,不考虑重传报文段的往返时间样本。
- 这样超时重传的时间就无法更新了。这会导致报文段反复被重传
解决2:
- 因此要对Karn算法进行修正
- 方法是:报文段每重传一次,就让RTO增大一些
- 典型的做法是将新RTO的值取为旧RTO的2倍
- 超时重传时间不能远大于往返时间,会浪费资源
- 超时重传时间不能小于往返时间,会造成不必要的重传
- 超时重传时间应当略大于往返时间,为了避免误差,应当选用一段时间内的加权的往返时间
- 因为出现超时重传时无法测准往返时间RTT的问题,因此需要判断当报文段重传后,就不能采用往返时间的样本
3.3.1 介绍 利用滑动窗口机制来实现流量控制,重点有两个,一个是接收方通过对已接收的数据进行累计确认,并调整窗口大小,来对发送方进行流控,第二个就是启动持续计时器来探知是否要发送零窗口探测报文,通过这两个就可以让接收方对发送方进行窗口大小的调控,以此做到了流量控制。
3.3.2 为什么要提出流量控制 一般来说,我们总是希望数据传输的更快一些,但是如果发送方把数据发送的过快,接收方就可能来不及接收,这就会造成数据的丢失。所以就需要进行流量控制, 流量控制简单说就是让发送方的发送速率不要太快,要让接收方来得及接收
3.3.3 流量控制 我们利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制 重点在于接收方根据自己的存储空间来决定自己的接收空间的大小,以此来限制发送方发送窗口的大小
过程:
说明:
- 接收方对发送方进行流控的时机就是自己接收窗口大小已经调整为0,或者超过一定时间还没接收到数据时进行的
- 接收方返回的数据解析
- ACK=1,这表示这个报文是确认报文
- ack=201,表示累计确认的字节数的下一个
- 已经接收到了200,所以下一个就是201,所以累计确认报文中写的ack就是201
- 表明让发送方发送的报文字节数从201开始
- rwnd=300,表示窗口大小
- 这个也表示字节数
- TCP传输的数据是面向字节流的
- 丢失的数据并不会立即重传,而是等到超时机制触发后才重传
- 在201-300号字节数据丢失后,得到接收方的累计确认,知道了自己的201-300的数据还需要重传,但是并不会立即重传,而是先重传301-400号,401-500号字节数据
- 一直等到超时机制触发后,才重传旧的数据
- 也就是会先传后面的数据,再传丢失的数据(此时不会失序,因为接收是有窗口的)
- 接收窗口的调整是通过自己的存储空间决定的,而发送窗口的大小是通过接收方发送的,每次进行流控都需要进行发送窗口的调控
接收方给发送方发送的确认报文丢失后会形成A和B主机的相互等待,这样就造成了死锁,需要通过一个持续计时器,当计时器为0时发送零窗口探测报文询问以此让接收方再次发送确认报文。这样就打破了死锁
3.3.4.1 死锁的形成
- 上述的流控当确认报文丢失后,会因A主机等待确认报文,B主机等待A主机的数据发送
- A主机和B主机形成互相等待现象,也就是死锁
说明:
- 持续计时器的启动时机为接收到了接收方发来的窗口为0的确认报文
- 持续计时器超时后发送的是零窗口探测报文
- 对接收方进行询问接收窗口是否为0,零窗口探测报文仅为一个字节数据
- 若接收方接接收到探测报文会进行确认,返回自己的窗口
- 如果返回的仍然是0窗口,那么再次启动计时器
- 如果零窗口探测报文丢失,会启动零窗口报文段的计时器,如果零窗口报文段丢失后,会在这个计时器的超时机制下进行重传
3.3.4.3 一些疑问 零窗口探测报文丢失后,是否仍然会死锁?
- 不会,零窗口报文段发送后会启动零窗口报文段的计时器,如果零窗口报文段丢失后,会在这个计时器的超时机制下进行重传
零窗口探测报文发送到主机B时,主机B的接收窗口为0,还能接收零窗口探测报文吗
- 是可以接收的
- TCP协议规定,即使接收窗口为0,也必须接收零窗口探测报文段、确认报文段、以及携带有紧急数据的报文段
- 一般来说我们总是希望数据传输的更快,但如果发送放把数据发送的过快,接收方就可能来不及接收,这样会造成数据丢失,因此就需要流控
- 所谓流控,就是让发送方的发送不要太快,要让接收方来得及接收
- 利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制 基本原理就是TCP接收方利用自己的接收窗口的大小来限制发送窗口的大小 TCP接收方根据自己的接收需要向发送方发送窗口大小。 如果TCP发送方收到接收方的零窗口通知后,应启动持续计时器。 持续计时器超时后,向接收方发送零窗口探测报文。
可靠传输是通过确认机制来实现的,接收方给发送方发送的确认报文带有的字段决定了发送方是否要重传,是否要滑动窗口的操作,以此做到了可靠传输
说明:
- TCP基于以字节为单位的滑动窗口来实现可靠传输 发送方在未收到接收方的确认时,可将发送窗口内还未发送的数据全部发送出去。 接收方只接收序号落入发送窗口内的数据
- 虽然发送方的发送窗口是根据接收方的接收窗口设置的,但在同一时刻,发送方的发送窗口并不综合接收方的接收窗口一样大,因为有一定的时间滞后
- 对于不按序到达的数据应如何处理,TCP并无明确规定
- TCP要求接收方必须有累积确认和捎带确认机制,这样可以减小传输开销,接收方可以在核实的时候发送确认,也可以在自己有数据要发送的时候把确认信息顺便捎带上
- TCP的通信是全双工通信。
C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
3.5 运输连接管理3.5.1 介绍TCP是面向连接的协议,它基于运输连接来传送TCP报文段,TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的部分。 TCP的运输连接管理就是使运输连接的建立和释放都能正常的进行。 共有三个阶段
- 建立TCP连接(三次握手)
- 数据传输
- 释放TCP连接(四次挥手)
3.5.2 三次握手过程
- TCP 连接的建立采用客户服务器方式。
- 主动发起连接建立的应用进程叫做TCP客户 (client)。
- 被动等待连接建立的应用进程叫做TCP服务器 (server)。
- “握手”需要在TCP客户端和服务器之间交换三个TCP报文段
过程示意图:
说明:
- 第一次握手是客户端向服务器端发送TCP连接请求 SYN=1表示的报文段不能携带数据,但会消耗掉一个序号 seq=x表示序号位 此时进入同步已发送状态
- 第二次握手是服务器端向客户端发送针对TCP连接请求的确认 ACK表示确认报文段 seq=y表示序号位,作为服务器进程所选择的初始序号 ack=x 1为确认序号字段,这是对客户进程所选择的初始序号的确认 SYN=1,不能传输数据 进入同步已接收状态
- 第三次握手是客户端向服务器端发送针对TCP连接请求的确认的确认 这是一个普通的TCP确认报文段 客户端发送后进入连接已建立状态,服务器端接收到后也进入连接已建立状态 可以携带数据,SYN不等于1
为什么必须要三次握手,不能两次握手?
采用三报文握手主要是为了防止已失效的连接请求报文段突然又传送到了TCK服务器端,导致服务器端无效浪费资源。
3.5.3.2 为什么需要四次挥手?
- TCP客户端和服务器端两方都需要在数据传送结束后发出连接释放的通知,
- 连接是双向的,TCP客户端发出的释放连接请求,服务器端在发出确认报文后,这种情况只是TCP客户端到TCP服务器端这个连接关闭掉了。TCP服务器端到客户端的连接还没有关闭掉
- 所以还需要服务器端发送释放连接请求报文,客户端发送确认报文后,这种方向的连接才关闭掉。
- 因此需要四次挥手才可以将两方的连接关闭掉
3.5.3.3 TCP客户进程在发送完最后一个确认报文后,为什么不直接进入关闭状态?而是要进入时间等待状态?
- 因为时间等待状态以及处于该状态2MSL时长,可以确保TCP服务器进程可以收到最后一个TCP确认报文段而进入关闭状态
- 另外,TCP客户进程在发送完最后一个TCP确认报文段后,在经过2MSL时长,就可以使本次连接持续时间内所产生的所有报文段都从网络中消失,这样就可以使下一个新的TCP连接中,不会出现旧连接中的报文段
- C 音视频开发学习资料:点击领取→音视频开发(资料文档 视频教程 面试题)(FFmpeg WebRTC RTMP RTSP HLS RTP)
TCP双方已经建立了连接,后来,TCP客户进程所在的主机突然出现了故障,TCP服务器进程以后就不能再收到TCP客户进程发来的数据,因此,应当有措施使TCP服务器进程不要再白白等待下去
4、TCP与UDP的对比
,