本文已参与「新人创作礼」活动,一起开启掘金创作之路。
什么是三次握手 (three-way handshake)?
TCP 建立连接的过程叫做握手,握手时在客户端和服务器之间交换三个TCP 报文段,称之为三报文握手。
三报文握手主要是为了防止已失效的连接请求报文段突然又传送到了而产生错误。
同时打开,同时关闭,半关闭(可能问到为什么需要三次握手、四次挥手等)
假设 A 为客户端,B 为服务器端。
- 首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。
- A 向 B 发送连接请求报文,同步位SYN=1,初始序号 seq=x没有确认号。
- B 收到连接请求报文,如果同意建立连接,则向 A 发送连接确认报文,同步位SYN=1,确认号ack=x+1,也选择一个初始序号seq=y,确认标志位ACK=1(统一建立连接后,ACK一直是1)
- A 收到 B 的连接确认报文后,还要向 B 发出确认,确认标志位ACK=1,序号seq= x+1,ack=y+1(SYN=0)。
- B 收到 A 的确认后,连接建立。
三次握手的原因
三次握手是为了保证建立一条正确、可靠的连接通道。
假如只进行一次握手,客户端给服务器发送连接请求后,并没法判断B是否收到请求并同意连接。
假如只进行两次握手,客户端发送连接请求,服务器端收到请求后会发回连接确认,那么连接就可以建立。但是如果,客户端发送的连接请求如果在网络中滞留,那么可能服务器端会隔很长一段时间才能收到并发回连接确认。客户端等待一个超时重传时间之后,就会重新发连接请求。如果这个滞留的连接请求最后还是到达了服务器,如果不进行三次握手,那么服务器就会打开两个连接。
如果有第三次握手,客户端会只对服务器第一次连接确认做出响应发回确认,服务器收不到第二次确认就不会再次打开连接。
总结:三次握手防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。
可以采用四次握手吗?为什么?
可以。但是会降低传输的效率。
四次握手是指:第二次握手Server只发送确认标志位ACK和确认号ack;第三次握手由Server发送SYN和初始序列号seq;原来协议中的第三次握手变为第四次握手。出于优化目的,四次握手中的二、三可以合并。
第三次握手中,如果客户端的ACK未送达服务器,会怎样?
由于Server没有收到ACK确认,会重发SYN+ACK(默认重发五次,之后自动关闭连接) ,Client收到后会重新传ACK给Server。
如果Client没有发出确认就向服务器发送数据,服务器会以RST包响应(TCP连接异常终止)。
如果已经建立了连接,但客户端出现了故障怎么办?
服务器有一个计时器,每次收到客户端的数据后会重置,若两小时没有收到客户端的任何数据,服务器就会发送探测报文段,每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
初始序列号是什么?
客户端A随机选择一个32位的序列号作为发送数据的初始序列号,比如为1000,以该序列号为原点,对传送的数据进行编号:1001、1002...三次握手时,把这个初始序列号传送给另一方B,B可以通过初始序列号确认数据编号是否合法;B发送给A的确认号可以告诉A已经接收到的数据有哪些,如果A收到了B的确认编号(acknowledge number)是2001,就说明编号为1001-2000的数据已经被B成功接受。
为什么
为什么初始序列号是随机的?
使用随机的序列号,是为了提高安全性,防止中间人攻击,TCP连接建立后通信时若序列号不对,则接收方会发回一个reset消息并关闭连接。随机的初始序列号使得AB通信时的序列号无法推测,若有C端在A和B通信时伪造其中一方给另一方发送数据,接收方接收到错误的序列号,则会关闭连接。