TCP ,丫的终于来了!!(二)

简介: 之前的文章一直在聊各种网络协议,那么从这篇文章开始,我就会和你聊一聊关于 TCP 协议的种种特征,比如 TCP 连接管理(也是这篇文章主要讨论的)、TCP 超时和重传、TCP 拥塞控制、TCP 数据流和窗口管理。

同时打开和同时关闭

还有一种比较非常规的操作,这就是两个应用程序同时主动打开连接。虽然这种情况看起来不太可能,但是在特定的安排下却是有可能发生的。我们主要讲述这个过程。

通信双方在接收到来自对方的 SYN 之前会首先发送一个 SYN,这个场景还要求通信双方都知道对方的 IP 地址 + 端口号

比如恋爱中的一对男女,他俩都同时说出了我爱你这个神圣的誓言,然后他俩对彼此的响应进行么么哒,这就是同时打开。

下面是同时打开的例子

微信图片_20220416165918.png

如上图所示,通信双方都在收到对方报文前主动发送了 SYN 报文,都在收到彼此的报文后回复了一个 ACK 报文。

一个同时打开过程需要交换四个报文段,比普通的三次握手增加了一个,由于同时打开没有客户端和服务器一说,所以这里我用了通信双方来称呼。

像同时打开一样,同时关闭也是通信双方同时提出主动关闭请求,发送 FIN 报文,下图显示了一个同时关闭的过程。

微信图片_20220416165926.png

同时关闭过程中需要交换和正常关闭相同数量的报文段,只不过同时关闭不像四次挥手那样顺序进行,而是交叉进行的。

聊一聊初始序列号

也许是我上面图示或者文字描述的不专业,初始序列号它是有专业术语表示的,初始序列号的英文名称是Initial sequence numbers (ISN),所以我们上面表示的 seq = v,其实就表示的 ISN。

在发送 SYN 之前,通信双方会选择一个初始序列号。初始序列号是随机生成的,每一个 TCP 连接都会有一个不同的初始序列号。RFC 文档指出初始序列号是一个 32 位的计数器,每 4 us(微秒) + 1。因为每个 TCP 连接都是一个不同的实例,这么安排的目的就是为了防止出现序列号重叠的情况。

当一个 TCP 连接建立的过程中,只有正确的 TCP 四元组和正确的序列号才会被对方接收。这也反应了 TCP 报文段容易被伪造 的脆弱性,因为只要我伪造了一个相同的四元组和初始序列号就能够伪造 TCP 连接,从而打断 TCP 的正常连接,所以抵御这种攻击的一种方式就是使用初始序列号,另外一种方法就是加密序列号。

TCP 状态转换

我们上面聊到了三次握手和四次挥手,提到了一些关于 TCP 连接之间的状态转换,那么下面我就从头开始和你好好梳理一下这些状态之间的转换。

首先第一步,刚开始时服务器和客户端都处于 CLOSED 状态,这时需要判断是主动打开还是被动打开,如果是主动打开,那么客户端向服务器发送 SYN 报文,此时客户端处于 SYN-SEND 状态,SYN-SEND 表示发送连接请求后等待匹配的连接请求,服务器被动打开会处于 LISTEN 状态,用于监听 SYN 报文。如果客户端调用了 close 方法或者经过一段时间没有操作,就会重新变为 CLOSED 状态,这一步转换图如下

微信图片_20220416165931.png

这里有个疑问,为什么处于 LISTEN 状态下的客户端还会发送 SYN 变为 SYN_SENT 状态呢?

知乎看到了车小胖大佬的回答,这种情况可能出现在 FTP 中,LISTEN -> SYN_SENT 是因为这个连接可能是由于服务器端的应用有数据发送给客户端所触发的,客户端被动接受连接,连接建立后,开始传输文件。也就是说,处于 LISTEN 状态的服务器也是有可能发送 SYN 报文的,只不过这种情况非常少见。

处于 SYN_SEND 状态的服务器会接收 SYN 并发送 SYN 和 ACK 转换成为 SYN_RCVD 状态,同样的,处于 LISTEN 状态的客户端也会接收 SYN 并发送 SYN 和 ACK 转换为 SYN_RCVD 状态。如果处于 SYN_RCVD 状态的客户端收到 RST 就会变为 LISTEN 状态。

微信图片_20220416165936.png

这两张图一起看会比较好一些。

这里需要解释下什么是 RST

这里有一种情况是当主机收到 TCP 报文段后,其 IP 和端口号不匹配的情况。假设客户端主机发送一个请求,而服务器主机经过 IP 和端口号的判断后发现不是给这个服务器的,那么服务器就会发出一个 RST 特殊报文段给客户端。

微信图片_20220416165940.png

因此,当服务端发送一个 RST 特殊报文段给客户端的时候,它就会告诉客户端没有匹配的套接字连接,请不要再继续发送了

RST:(Reset the connection)用于复位因某种原因引起出现的错误连接,也用来拒绝非法数据和请求。如果接收到 RST 位时候,通常发生了某些错误。

上面没有识别正确的 IP 端口是一种导致 RST 出现的情况,除此之外,RST 还可能由于请求超时、取消一个已存在的连接等出现。

位于 SYN_RCVD 的服务器会接收 ACK 报文,SYN_SEND 的客户端会接收 SYN 和 ACK 报文,并发送 ACK 报文,由此,客户端和服务器之间的连接就建立了。

微信图片_20220416165944.png

这里还要注意一点,同时打开的状态我在上面没有刻意表示出来,实际上,在同时打开的情况下,它的状态变化是这样的。

微信图片_20220416165948.png

为什么会是这样呢?因为你想,在同时打开的情况下,两端主机都发起 SYN 报文,而主动发起 SYN 的主机会处于 SYN-SEND 状态,发送完成后,会等待接收 SYN 和 ACK , 在双方主机都发送了 SYN + ACK 后,双方都处于 SYN-RECEIVED(SYN-RCVD) 状态,然后等待 SYN + ACK 的报文到达后,双方就会处于 ESTABLISHED 状态,开始传输数据。

好了,到现在为止,我给你叙述了一下 TCP 连接建立过程中的状态转换,现在你可以泡一壶茶喝点水,等着数据传输了。

好了,现在水喝够了,这时候数据也传输完成了,数据传输完成后,这条 TCP 连接就可以断开了。

现在我们把时钟往前拨一下,调整到服务端处于 SYN_RCVD 状态的时刻,因为刚收到了 SYN 包并发送了 SYN + ACK 包,此时服务端很开心,但是这时,服务端应用进程关闭了,然后应用进程发了一个 FIN 包,就会让服务器从 SYN_RCVD -> FIN_WAIT_1 状态。

微信图片_20220416165955.png

然后把时钟调到现在,客户端和服务器现在已经传输完数据了 ,此时客户端发送了一条 FIN 报文希望断开连接,此时客户端也会变为 FIN_WAIT_1 状态,对于服务器来说,它接收到了 FIN 报文段并回复了 ACK 报文,就会从 ESTABLISHED -> CLOSE_WAIT 状态。

微信图片_20220416165959.png

位于 CLOSE_WAIT 状态的服务端会发送 FIN 报文,然后把自己置于 LAST_ACK 状态。处于 FIN_WAIT_1 的客户端接收 ACK 消息就会变为 FIN_WAIT_2 状态。

这里需要先解释一下 CLOSING 这个状态,FIN_WAIT_1 -> CLOSING 的转换比较特殊

相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
2天前
|
网络协议 算法 网络性能优化
TCP和UDP详解2
TCP和UDP详解
34 0
|
2天前
|
网络协议 算法 Java
|
6月前
|
网络协议
08 tcp的2MSL问题
08 tcp的2MSL问题
27 0
|
7月前
|
存储 网络协议 程序员
TCP VS UDP
TCP VS UDP
34 0
|
缓存 网络协议 安全
TCP为什么安全
老八股了,都说TCP比UDP安全,那他安全再哪呢。。
169 0
|
缓存 网络协议 Linux
|
缓存 网络协议 算法
|
存储 缓存 网络协议
TCP、UDP详解
TCP、UDP详解
199 0
|
网络协议 Linux
TCP 才不傻!
TCP 三次握手和四次挥手的一些疑问
TCP 才不傻!
|
网络协议 网络性能优化
TCP ,丫的终于来了!!(三)
之前的文章一直在聊各种网络协议,那么从这篇文章开始,我就会和你聊一聊关于 TCP 协议的种种特征,比如 TCP 连接管理(也是这篇文章主要讨论的)、TCP 超时和重传、TCP 拥塞控制、TCP 数据流和窗口管理。
TCP ,丫的终于来了!!(三)