在学习TCP协议之前,我们了解一下TCP头的报文格式
记住这个报文格式,接下来的内容都是基于这个的
#### 三次握手
首先我们从一个两个人打电话的例子来描述一下:
这个过程其实可以完美的解释三次握手的机制。我们知道,网络环境总是不安全的,只有至少经过这三次交互才能确认两方的发送和接受能力都没问题。
我们来看一下这几步分别确定了什么:
三次握手除了上方的连接之外,还会牵扯到我们文章刚开始时说的包的序号和状态位,下面这个图就是一个完整的三次握手流程
一开始,A和B都处于 CLOSED
状态。先是B主动监听某个端口,处于 LISTEN
状态。然后A主动发起连接 SYN
,之后处于 SYN-SENT
状态。B收到发起的连接,返回 SYN
,并且 ACK
A的 SYN
,之后处于 SYN-RCVD
状态。A收到B发送的 SYN
和 ACK
之后,发送 ACK
的 ACK
,之后处于 ESTABLISHED
状态,因为它一发一收成功了。服务端收到 ACK
的 ACK
之后,处于 ESTABLISHED
状态,因为它也一发一收了
#### 四次挥手
理解了三次握手之后再看四次挥手就比较简单了。直接看图
当消息传输完毕后,断开链接的过程就是这样的:
上方有一个字段MSL,它是报文在网络上的最大生存时间。那么为什么要等待2MSL才会断开链接呢?
主要是因为报文的最大生存时间是1MSL,如果A直接关闭的话,它占用的端口如果马上建立了一个新的连接,那么新的连接就有可能收到刚才B发送的迟到的报文,从而误以为是发给自己的
#### TCP消息的顺序性和可靠性
刚才我们已经知道了,TCP中每一个包都有一个序号,为了保证顺序性和可靠性,TCP的发送方和接受方都是需要记录这些序号相关的数据
为了记录所有发送的包,发送端需要记录以下这些场景的数据:
也就是如下图这样
而接收端记录的内容要简单一些:
基于上面两个图,我们来研究一下顺序性和可靠性:
在发送端来看,1、2、3 已经发送并确认;4、5、6、7、8、9 都是发送了还没确认;10、11、12 是还没发出的;13、14、15 是接收方没有空间,不准备发的。
在接收端来看,1、2、3、4、5 是已经完成 ACK
,但是没读取的;6、7 是等待接收的;8、9 是已经接收,但是没有 ACK
的。
发送端和接收端当前的状态如下:
ACK
了,但是发送方还没收到,有可能丢了,有可能在路上。ACK
。而当发生丢包问题,或者不能保证有序性时,有这几种方式可以处理:超时重传、快速重传、SACK
#### TCP滑动窗口
在TCP的传输的时候,我们知道如果一个数据比较大的话就会把这个数据划分为多个包来进行发送。而为了保证消息的顺序性和可靠性的话就必须如下图所示当一个包确认后才能发送下一个包
但是这样一来就会存在一个问题,每发送一个数据包,都需要得到接收端的确认应答以后才能继续,那这个等待确认包的过程中就会很浪费时间。
为了应对这种场景,TCP协议就引入了滑动窗口的概念,再次拿来刚才用到的这个图
这里我们假设滑动窗口的大小为9不变的,也就是说这个机制可以一次性的发送一个窗口数量的包。这个时候每当收到几个应答包的时候这个窗口就会后移一个位置,假如这个时候收到了4号消息的ack,那么这个数据就成这样了
这样一个窗口根据消息的ack
不断后移的过程就称为滑动窗口
#### TCP流量控制
上方说到了TCP发送方的滑动窗口,但是接收端处理数据包的能力是不同的,比如说:
为了避免这种现象的发生,TCP提供了流量控制的机制,我们刚才说到的假设的滑动窗口的大小是固定的,而流量控制就是根据接收端的能力而去调整窗口的大小,这个流程是这样的:
发送端第一次以窗口大小(该窗口大小是根据链路带宽的大小来决定的)发送数据包,接收端接收这些数据包,并返回确认应答包,告诉发送端自己下次希望收到的数据包是多少(新的窗口大小),发送端收到确认应答包以后,将以该窗口大小进行发送数据包
原文:https://www.cnblogs.com/zhixiang-org-cn/p/12449934.html