TCP/IP总结
一、为什么TCP建立连接需要三次握手?
- 若只有2次握手,服务器端需要再收到SYN发出SYN+ACK后就建立连接。
若SYN+ACK丢失,客户端会重发SYN,这会导致服务器必须关闭旧连接重新建立新连接。
若网络不稳定,服务器端可能需要反复重建连接,无谓消耗资源。
只有2次握手,服务器容易遭受攻击,大量消耗资源。
-
三次握手足以保证连接的可靠建立,不需要四次握手。
-
客户端会在发出第三次握手数据包后创建连接。
若第三次握手数据包丢失,服务器端可以重发第二次握手数据包,若重发多次都收不到回复,可以销毁连接。
在服务器端收到第三次握手数据包之前,若客户端向服务器端发送数据,服务器端会发送RST重置连接。
二、为什么TCP关闭连接需要四次握手?
- 四次握手可以使双方实现半关闭,先由主动关闭方关闭自己的发送,再由被动关闭方关闭自己的发送,双方都不再发送数据之后才关闭连接,
这样有利于被动关闭一方妥善处理已接收未处理的数据包。
- 三次握手不足以保证连接的可靠关闭,因为若被动关闭一方发出的第三次握手数据包丢失,主动关闭一方就无法关闭连接,
被动关闭一方需要第四次握手来判断是否需要重发第三次握手数据包,确保主动关闭一方可靠关闭连接。
主动关闭一方会在发出第四次握手数据包之后关闭。若第四次握手数据包丢失,被动关闭端会重发第三次握手数据包。
若一直收不到第四次握手数据包,被动关闭端会在重发几次第三次握手数据包后强制关闭连接。
三、TIME_WAIT状态
- 主动关闭端会进入TIME_WAIT状态,可能是客户端,也可能是服务器端。
当网络出现异常、客户端崩溃或者被恶意攻击时,服务器端需要主动关闭连接来释放连接占用的内存资源。
- TIME_WAIT状态的作用
(1)防止历史连接中的数据,被后面相同四元组的连接错误的接收。
(2)保证「被动关闭连接」的一方,能被正确的关闭。
- TIME_WAIT持续的时间是2MSL,linux系统大约60秒。
时间设为2MSL的原因是,主动关闭端收到FIN后发出的ACK包可能会丢失,若ACK丢失,被动关闭端会重发FIN,
从被动关闭端发出FIN到主动关闭端发出的ACK到达被动关闭端,这段时间最大为约2MSL。
若被动关闭端在ACK消亡之前就重发了FIN,则此FIN到达主动关闭端的最大时间距ACK发出的时间小于2MSL,
这种情况主动关闭端会重发ACK。
若被动关闭端在ACK消亡之后过一会才重发FIN,则此FIN到达主动关闭端的最大时间距ACK发出的时间大于2MSL,
这种情况主动关闭端已退出TIME_WAIT状态。
主动关闭端发出ACK之后,经过2MSL仍未收到被动关闭端重发的FIN,说明对方已正常关闭,若因网络异常
导致重发的FIN丢失,则不应继续等待下去,继续等下去会导致资源不能及时释放,弊大于利。
被动关闭端最后一次发出的数据包会在FIN之前发出,其到达主动关闭端的最大时间是MSL,此时主动关闭端尚未退出
TIME_WAIT状态,若最后一个数据包在FIN之后到达,会被丢弃。
- 如果客户端TIME_WAIT状态持续时间太短或跳过TIME_WAIT状态直接关闭对连接双方有什么坏处?
客户端TIME_WAIT状态持续时间太短,会过早关闭连接。
(1)对客户端的坏处
如果客户端每次都使用不同的端口号建立连接,旧连接的过期失效数据包不会影响新连接。
如果客户端使用相同的端口号建立连接,旧连接的过期失效数据包可能会被新连接接收。
(2)对服务器端的坏处
客户端关闭旧连接的ACK可能会丢失,导致服务器重发的FIN收不到回复,不能及时关闭连接释放资源,或者客户端对重发的
FIN回复RST,强制关闭连接,这种关闭方式不够妥当。
- TIME_WAIT状态的优点:
(1)有利于保障被动关闭端正常关闭,及时释放资源。
(2)有利于丢弃已关闭连接的过期数据包,避免少数因网络异常迟到的已关闭连接的过期数据包被当做新连接的有效数据接收。
若连接关闭时不经TIME_WAIT状态就立即释放资源,之后当客户端使用相同的端口号重新连接时,已关闭连接的少数因网络
异常迟到的过期数据包可能会被当做新连接的有效数据接收。
若过期数据包的SEQ小于新连接的SEQ,会被当做重复数据包直接丢弃。
若过期数据包的SEQ大于新连接的SEQ,服务器可能会认为中间SEQ的数据包尚未到达,并把该数据包当做有效数据接收。
解决这一问题的办法是,客户端每次发起连接时使用系统随机分配的端口,尽量避免使用相同的端口号。
- TIME_WAIT时间太长的缺点,如何减小缺点的影响。
TIME_WAIT时间太长对客户端影响较小,对服务器端影响较大。
(1)对客户端的缺点是会占用端口和内存资源。客户端的端口资源相对丰富,影响较小,主要是占用过多内存资源。
解决办法是,每次发起连接时更换端口号,开启net.ipv4.tcp_tw_reuse和tcp_timestamps选项。
(2)对服务器端的影响是占用内存资源。
解决办法是,减小net.ipv4.tcp_max_tw_buckets,当处于TIME_WAIT状态的连接达到一定数量时直接发送RST重置连接。
- 连接双方崩溃重启
(1)服务器端崩溃重启
如果服务器端崩溃重启,收到客户端数据之后,协议栈发现连接不存在,会发送RST提醒客户端重置连接。
(2)客户端崩溃重启
如果客户端崩溃重启,会重新连接服务器端。若使用不同的端口号,服务器端原来的连接会因超时在垃圾回收时被关闭。
若客户端使用相同的端口号,服务器端收到SYN时发现原来的连接仍在,会主动关闭原来的连接。新的SYN可能会因为原来的连接处于TIME_WAIT状态而被丢弃或者发送RST重置连
- RST重置连接会进入TIME_WAIT状态吗?
不会,TCP RST 重置连接不会进入 TIME_WAIT 状态。TIME_WAIT 仅出现在主动正常关闭连接的一方(即发送了最后一个 ACK 的一方),是四次挥手的正常终点,用于确保可靠终止和防止旧报文干扰。
RST(复位) 是异常或强制终止连接的方式,收到 RST 的一方会立即释放连接资源,跳过所有关闭状态(包括 FIN_WAIT、TIME_WAIT 等),不进行 2MSL 等待。因此,只要连接是被 RST 终止的(无论哪一端发起),都不会进入 TIME_WAIT 状态。