TCP建立连接和关闭连接的过程
首先我们来回顾下我们以前了解过的,TCP头部结构有6个标识位
- SYN:仅在三次握手建立连接时有效,表示同步报文段。
- ACK:对TCP请求的确认标志。
- FIN:标志用来结束一个TCP连接,标识此报文段是一个结束报文段
以上就是我们讲到以下内容的时候需要用到的知识点
三次握手建立连接
开始介绍一下三次握手的过程:
- 第一次握手:其实是客户端发送一个带有SYN的数据报文段发送给服务器,对应在图片中就是从主机A->主机B(SYN=1,seq=i),seq为对应序列号为i。之后主机A进入SYN_SENT状态。同时等待服务器的确认
- 第二次握手:服务器收到同步报文段后(也就是带有SYN的同步报文段),必须确定客户的同步报文段。然后自己也发送一个带有SYN的报文段,对应到图片中也就死第二个报文段,其中SYN=1,表示这是一个同步报文段,ACK=1,表示这是一个确认报文段,确认序号值为i+1,序号值为j。
- 第三次握手:这次就是客户端收到确认同步报文段后,它向服务器发送确认包,对应到图片中也就是第三个报文段,ack=1也就是表示这是一个确认报文段,确认序号为j+1
三次握手建立后,客户端与服务器开始传送数据。
三次握手示意图:
四次握手关闭连接
接下来,我们来介绍下四次握手关闭
- 第一次握手:表示客户端A发送给服务器一个带有SYN的结束报文段,用来关闭客户端A到服务端B的数据传送,对应到图片中也就是第一个报文段,FIN=1,seq=i,表示一个结束报文段
- 第二次握手:服务端B接收到这个结束报文段后,它返回一个确认报文段,对应到图片中就是第二个确认报文段。其中ACK=1,ack=i+i,表示一个确认报文段,确认序号为i+1.
- 第三次握手:服务器B关闭与客户端A的连接,他发送一个带有SYN结束报文段,对应图片上第三个报文段,其中 SYN=1,seq=j,表示结束报文段,序号为j。
- 第四次握手:客户端A返回一个确认报文段,其中确认序号为j+1,对应图片上为第四个报文段,ACK=1,ack=j+1。
总结:为什么建立连接需要三次握手?为什么关闭连接需要四次握手?为什么建立连接需要三次握手呢?
接受连接缺需要4次握手,LISTEN状态下建立连接后,它可以把同步报文段和确认报文段合并成一个报文段来进行发送,确认报文段起到应达作用,同步报文段起到同步作用,也就是三次握手中的第二个报文段其实是发挥了两个作用
在关闭连接时,当收到对方的结束报文段时,表示对方没有数据发给你了,但是自己的数据未必全部发送完毕,所以你可能还需要继续发送一些数据之后在发送结束报文段给对方了表示你同意现在可以断开连接,所以关闭连接需要四次握手
如果把三次握手改成两次握手,就有可能发生死锁。关于死锁,(搜索一下)
四次握手示意图:
TIME_WAIT状态的含义
在TCP详解(二)中,提到过,当客户端收到服务器的结束报文段后,不会立即进入CLOSED状态,而是转移到TIME_WAIT状态下,在这个状态下,客户端要等待一段2倍的MSL(报文段最大生存时间)时间。等待这个时间后才能完全关闭。TIME_WAIT状态的持续时间是MSL的2倍,这就足以让某个方向上的分组最多存活msl秒即被丢弃,另一个方向上的应答最多存活msl秒也被丢弃。 通过实施这个规则,我们就能保证每成功建立一个TCP连接时。来自该链接先前化身的重复分组都已经在网络中消逝了。
TIME_WAIT状态存在的原因有两点:
可靠的终止TCP连接:
例如在四次握手时,如果第三个报文段丢失,这个时候服务器将重新发送这个报文段,所以客户端需要停留在摸个状态来处理重复信息。否则客户端将会向服务器发送复位报文段,让服务器误认为这是一个错误
保证延迟来的TCP报文段有足够的时间去识别并丢弃:
在Linux系统上,一个TCP端口不能被同时打开多次,当一个TCP连接处于TIME_WAIT状态时,我们将无法立即使用该连接占用的端口建立一个新连接。
但是我们反过来考虑,如果不存在这种机制,那么服务器刚关闭连接,又建立了一个类似的连接,成为“原链接化身”,这个“化身“就有可能就收到属于原来连接的数据报文段,这种情况是不允许出现的。
IME_WAIT状态过多的缺点:
- 根据上诉,我们可以了解到,如果IME_WAIT状态过多会占用大量的端口号,占用系用资源
IME_WAIT状态过多的处理方法
修改内核参数
尽可能被动关闭连接
将长连接修改为短连接
通过套接字选项尽可能回避IME_WAIT状态带来的负面影响