为了准确无误地把数据送达目标处,TCP协议采用了三次握手策略。
TCP 三次握手漫画图解
简单示意图: TCP三次握手
客户端–发送带有 SYN 标志的数据包–一次握手–服务端
服务端–发送带有 SYN/ACK 标志的数据包–二次握手–客户端
客户端–发送带有带有 ACK 标志的数据包–三次握手–服务端
为什么要三次握手
三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的。
第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常
第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常
第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常
所以三次握手就能确认双发收发功能都正常,缺一不可。
为什么要传回 SYN
接收端传回发送端所发送的 SYN 是为了告诉发送端,我接收到的信息确实就是你所发送的信号了。
SYN 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN
消息,服务器使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK(Acknowledgement[汉译:确认字符
,在数据通信传输中,接收站发给发送站的一种传输控制字符。它表示确认发来的数据已经接受无误。
])消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。
传了 SYN,为啥还要传 ACK
双方通信无误必须是两者互相发送信息都无误。传了 SYN,证明发送方到接收方的通道没有问题,但是接收方到发送方的通道还需要 ACK 信号来进行验证。
四次挥手
断开一个 TCP 连接则需要“四次挥手”:
客户端-发送一个 FIN,用来关闭客户端到服务器的数据传送
服务器-收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加1 。和 SYN 一样,一个 FIN 将占用一个序号
服务器-关闭与客户端的连接,发送一个FIN给客户端
客户端-发回 ACK 报文确认,并将确认序号设置为收到序号加1
为什么要四次挥手
任何一方都可以在数据传送结束后发出连接释放的通知,待对方确认后进入半关闭状态。当另一方也没有数据再发送的时候,则发出连接释放通知,对方确认后就完全关闭了TCP连接。
举个例子:A 和 B 打电话,通话即将结束后,A 说“我没啥要说的了”,B回答“我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话,于是 B 可能又巴拉巴拉说了一通,最后 B 说“我说完了”,A 回答“知道了”,这样通话才算结束。
再举个例子:
- 客户端 告诉 服务器端我要关闭连接
- 服务器端 响应 说 我知道了;不再接收新的东西
- 服务器端 说 我现在要关闭链接了
- 客户端说 可以关闭了; ----》 通道关闭
面试时怎么回答:
说说计算机网络中TCP的三次握手吧
-
首先客户端的协议栈向服务端发送SYN包,同时告诉服务端当前发送的序列号是X,此时客户端进入 SYNC_SENT状态
-
服务端的协议栈收到这个包以后,使用 ACK 应答,此时应答的值为 X+1,表示对 SYN 包 J 的确认,同时服务端也发送一个SYN包,告诉客户端当前我的发送序列号是Y,此时服务端进入SYNC_RCVD状态
-
客户端协议栈收到 ACK 以后,应用程序通过connect调用表示服务端的单向连接成功,此时状态为ESTABLISHED,同时客户端协议栈对服务器端的 SYN 进行应答,此时数据为Y+1
-
服务端收到客户端的应答包,通过accept阻塞调用返回,此时服务端到客户单的单向连接也建立成功,服务器将进入ESTABLISHED状态
如果客户端发送的SYN丢失了或者其他原因导致Server无法处理,是什么原因?
这个场景非常常见,没有万无一失。在TCP的可靠传输中,如果SYN包在传输的过程中丢失,此时Client段会触发重传机制,但是也不是无脑的一直重传过去,重传的次数是受限制的,可以通过 tcp_syn_retries 这个配置项来决定。如果此时 tcp_syn_retries 的配置为3,那么其过程如下
当 Client 发送 SYN 后,如果过了1s还没有收到 Server 的回应,那么进行第一次的重传。如果经过了2s没有收到Sever的响应进行第二次的重传,一直重传tcp_syn_retries次。这里的重传三次,意味着当第一次发送SYN后,需要等待(1 +2 +4 +8)秒,如果还是没有响应,connect就会通过ETIMEOUT的错误返回。
过多的TIMEWAIT怎么办,什么原因造成的?
在TCP的四次挥手过程中,发起连接断开的一方会进入TIME_WAIT的状态。通常一个TCP连接通过对外开发端口的方式提供服务,在高并发的情况下,每个连接占用一个端口,但是端口是有限的以致于可能导致端口耗尽,所以就会出现’“服务时而好时而坏的情况”。
如下图所示的TCP四次挥手,TCP连接准备终止的时候会发送FIN报文,主机2进入CLOSE_WAIT状态并发送ACK应答。主机1会在TIMEWAIT停留2MSL的时间。
为什么不直接进入CLOSE转态,而是需要先等待2MSL,这段时间在干啥?
第一个原因是为了确保最后的ACK能够正常接收,从而有效的正常关闭。怎么理解,科学家们在设计TCP的时候,假设TCP报文会出错从而开始重传,如果主机1的报文没有传输成功,那么主机2就会重发FIN报文,此时主机1没有维护TIME_WAIT状态,就会失去上下文从而恢复RST,导致服被动关闭一方出现错误。
第二个原因是让旧链接的重复分节在网络中自然消失。
一次网络通信可能经过无数个路由器,交换机,不知道到底会是哪个环节出问题。我们为了标识一个连接,通过四元组的方式[源IP,源端口,目的IP,目的端口]。假设此时两个连接A,B。A连接在中途中断了,此时重新创建B连接,这个B连接的四元组和A连接一样,如果A连接经过一段时间到达了目的地,那么B连接很有可能被认为是A连接的一部分,这样就会造成混乱。所以TCP设置了这样一个机制,让两个方向的分组都被丢弃。
那么TIME_WAIT有哪些危害?
过多的连接势必造成内存资源的浪费
对端口的占用。可开启的端口也就32768~61000