今天摆烂了,随便写
参考内容
https://segmentfault.com/a/1190000020610336
https://blog.csdn.net/qq_36653524/article/details/102843211
https://blog.csdn.net/u012478275/article/details/99624506
Wireshark TCP 状态解析
SYN :建立连接
FIN :关闭连接
ACK :响应
PSH :有 DATA 数据传输
RST :连接重置
ACK 可能与 SYN,FIN 等 同时使用 的,比如 SYN 和 ACK 可能同时为 1,它表示的就是建立连接之后的响应

SYN 和 ACK 同时为 1
如果只是单个的一个 SYN,表示的只是建立连接。

单 SYN
TCP 的几次握手就是通过这样的 ACK 表现出来的。
SYN 与 FIN 是 不会 同时为 1 的,因为前者表示的是建立连接,而后者表示的是断开连接。
RST 一般是在 FIN 之后才会出现为1的情况,表示的是连接重置。
一般当出现 FIN 包或 RST 包时,我们便认为客户端与服务器端断开了连接;而当出现 SYN 和 SYN+ACK 包时,我们认为客户端与服务器建立了一个连接。
PSH 为 1 的情况,一般只出现在 DATA 内容不为 0 的包中,也就是说 PSH 为 1 表示的是有真正的 TCP 数据包内容被传递。

PSH 为 1
TCP 的连接建立和连接关闭,都是通过 请求-响应 的模式完成的。
三次握手
1、第一次握手:主机 A 发送位码为 syn=1,随机产生 seq number=1845044590 的数据包到服务器,主机 B 由 SYN=1 知道,A 要求建立联机。
2、第二次握手:主机 B 收到请求后要确认联机信息,向 A 发送 ack number=(主机 A 的 seq+1),syn=1,ack=1,随机产生 seq=468935965 的包。
3、第三次握手:主机 A 收到后检查 ack number 是否正确,即第一次发送的 seq number+1,以及位码 ack 是否为 1,若正确,主机 A 会再发送 ack number=(主机 B 的 seq+1),ack=1,主机 B 收到后确认 seq 值与 ack=1 则连接建立成功。

第一次握手

第二次握手

第三次握手
必要性
tcp 是面向连接,一次握手肯定建立不了连接。客户机给服务器发出请求信息却没有得到回应,客户机是没法判定是否发送成功然后建立连接的。
假设只有两次握手:
A 想要建立连接时发送一个 SYN,然后等待 ACK,结果 SYN 因为网络问题没有及时到达 B。A 在一段时间内没收到 ACK 后,再发送一个 SYN,这次 B 顺利收到并返回 ACK 给 A,A 也收到 ACK,这时A发送的第一个SYN终于到了B,对于B来说这是一个新连接请求,然后B又为这个连接申请资源,返回ACK,然而这个SYN是个无效的请求,A收到这个SYN的ACK后也并不会理会它,而B却不知道,B会一直为这个连接维持着资源,造成资源的浪费。
A 发送 SYN ,但是网络延迟没收到。
A 再次发送 SYN,并收到后并返回 ACK,ACK 成功到达 A,A 和 B 建立连接。
A 的第一个 SYN 到达 B,B 再次返回 ACK,但是由于第一个 SYN 已经无效,A 收到 AC K后不会理会,但是 B 不知道 A 的情况,B 会以为连接成功并一直占用资源。
握手出错时的应对
第一次握手 A 发送 SYN 传输失败 ,A,B 都不会申请资源,连接失败。如果一段时间内发出多个 SYN 连接请求,那么 A 只会接受最后发送的 SYN 的 SYN+ACK 回应,忽略其他回应全部回应,B 中多申请的资源也会释放。
第二次握手 B 发送 SYN+ACK 传输失败 ,A 不会申请资源,B 申请了资源,但收不到 A 的 ACK,过一段时间释放资源。如果是收到了多个 A 的SYN请求,B 都会回复 SYN+ACK,但 A 只会承认其中它最早发送的那个 SYN 的回应,并回复最后一次握手的 ACK。
第三次握手 ACK 传输失败 ,B 没有收到 ACK,释放资源,对于后序的 A 的传输数据返回 RST。实际上 B 会因为没有收到 A 的 ACK 会多次发送 SYN+ACK,次数是可以设置的,如果最后还是没有收到 A 的 ACK,则释放资源,对 A 的数据传输返回 RST。
四次挥手
1、 关闭客户端到服务器的连接:首先客户端 A 发送一个 FIN,用来关闭客户到服务器的数据传送,然后等待服务器的确认。其中终止标志位 FIN=1,序列号 seq=u。
2、 服务器收到这个 FIN,它发回一个 ACK,确认号 ack 为收到的序号加 1。
3、 关闭服务器到客户端的连接:服务端发送一个 FIN 给客户端。
4、 客户段收到 FIN 后,并发回一个 ACK 报文确认,并将确认序号 seq 设置为收到序号加 1。
目前手上没包,也懒得抓了。不贴图了。
必要性
这由 TCP 的半关闭(half-close)造成的。所谓的半关闭,其实就是 TCP 提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。当服务端收到客户端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。但是关闭连接时,当服务端收到 FIN 报文时, 很可能并不会立即关闭 SOCKET ,所以只能先回复一个 ACK 报文,告诉客户端,"你发的 FIN 报文我收到了"。只有等到我服务端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。故需要四次挥手。
挥手出错时的应对
第一次挥手丢失 :当客户端向服务端发送 FIN 报文,此时客户端的连接进入到 FIN_WAIT_1 状态。正常情况下,如及时收到服务端 ACK,则变为 FIN_WAIT2 状态。如第一次挥手丢失,客户端会触发超时重传机制,重传 FIN 报文,重发次数由 tcp_orphan_retries 参数控制。当客户端重传 FIN 报文的次数超过 tcp_orphan_retries 后,就不再发送 FIN 报文,直接进入到 close 状态。
第二次挥手丢失 :服务端收到客户端的第一次挥手后,回一个 ACK 确认报文,服务端进入 CLOSE_WAIT 状态。ACK 不会重传,如果服务端的第二次挥手丢失了,客户端会触发超时重传机制,重传 FIN 报文,直到收到服务端的第二次挥手,或者达到最大的重传次数。当客户端收到第二次挥手,客户端就会处于 FIN_WAIT2 状态,此状态需等服务端发送第三次挥手,也就是服务端的 FIN 报文。
第三次挥手丢失 :服务端收到客户端的 FIN 后,自动回复 ACK,同时连接处于 CLOSE_WAIT 状态。服务端处于 CLOSE_WAIT 状态时,调用了 close 函数发出 FIN 报文,同时连接进入 LAST_ACK 状态,等待客户端返回 ACK 来确认连接关闭。如迟迟收不到这个 ACK,服务端就会重发 FIN 报文,重发次数仍然由 tcp_orphan_retries 参数控制,与客户端重发 FIN 的重传次数控制方式是一样的。
第四次挥手丢失了 :当客户端收到服务端的第三次挥手的 FIN 报文后,就会回 ACK 报文,也就是第四次挥手,此时客户端连接进入 TIME_WAIT 状态。Linux 中,TIME_WAIT 状态持续 60 秒后进入关闭状态。服务端没有收到 ACK 报文前,还是处于 LAST_ACK 状态。如果第四次挥手的 ACK 报文没有到达服务端,服务端就会重发 FIN 报文,重发次数仍由 tcp_orphan_retries 控制。