什么是三次握手和四次握手
- 1. 三次握手
-
- 1.1 什么是三次握手 (three-way handshake)?
- 1.2 tcp建立连接可以两次握手吗?为什么?
- 1.3 可以采用四次握手吗?为什么?
- 1.4 第三次握手中,如果客户端的ack未送达服务器,会怎样?
- 1.5 如果已经建立了连接,但客户端出现了故障怎么办?
- 1.6 初始序列号是什么?
- 2. 四次挥手
-
- 2.1 什么是四次挥手?
- 2.2 为什么不能把服务器发送的ack和fin合并起来,变成三次挥手(close_wait状态意义是什么)?
- 2.3 如果第二次挥手时服务器的ack没有送达客户端,会怎样?
- 2.4 客户端time_wait状态的意义是什么?
1.1 什么是三次握手 (three-way handshake)?
- 第一次握手:client将syn置1,随机产生一个初始序列号seq发送给server,进入syn_sent状态;
- 第二次握手:server收到client的syn=1之后,知道客户端请求建立连接,将自己的syn置1,ack置1,产生一个acknowledge number=sequence number 1,并随机产生一个自己的初始序列号,发送给客户端;进入syn_rcvd状态;
- 第三次握手:客户端检查acknowledge number是否为序列号 1,ack是否为1,检查正确之后将自己的ack置为1,产生一个acknowledge number=服务器发的序列号 1,发送给服务器;进入established状态;服务器检查ack为1和acknowledge number为序列号 1之后,也进入established状态;完成三次握手,连接建立。
1.2 tcp建立连接可以两次握手吗?为什么?
不可以。有两个原因:
- 首先,可能会出现已失效的连接请求报文段又传到了服务器端。
client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用 “三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采用 “三次握手” 的办法可以防止上述现象发生。例如刚才那种情况,client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。 - 其次,两次握手无法保证client正确接收第二次握手的报文(server无法确认client是否收到),也无法保证client和server之间成功互换初始序列号。
1.3 可以采用四次握手吗?为什么?
可以。但是会降低传输的效率。
四次握手是指:第二次握手:server只发送ack和acknowledge number;而server的syn和初始序列号在第三次握手时发送;原来协议中的第三次握手变为第四次握手。出于优化目的,四次握手中的二、三可以合并。
1.4 第三次握手中,如果客户端的ack未送达服务器,会怎样?
server端:
由于server没有收到ack确认,因此会重发之前的syn ack(默认重发五次,之后自动关闭连接进入closed状态),client收到后会重新传ack给server。
client端,两种情况:
- 在server进行超时重发的过程中,如果client向服务器发送数据,数据头部的ack是为1的,所以服务器收到数据之后会读取 ack number,进入 establish 状态
- 在server进入closed状态之后,如果client向服务器发送数据,服务器会以rst包应答。
1.5 如果已经建立了连接,但客户端出现了故障怎么办?
服务器每收到一次客户端的请求后都会重新复位一个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。
1.6 初始序列号是什么?
tcp连接的一方a,随机选择一个32位的序列号(sequence number)作为发送数据的初始序列号(initial sequence number,isn),比如为1000,以该序列号为原点,对要传送的数据进行编号:1001、1002…三次握手时,把这个初始序列号传送给另一方b,以便在传输数据时,b可以确认什么样的数据编号是合法的;同时在进行数据传输时,a还可以确认b收到的每一个字节,如果a收到了b的确认编号(acknowledge number)是2001,就说明编号为1001-2000的数据已经被b成功接受。
2.1 什么是四次挥手?
- 第一次挥手:client将fin置为1,发送一个序列号seq给server;进入fin_wait_1状态;
- 第二次挥手:server收到fin之后,发送一个ack=1,acknowledge number=收到的序列号 1;进入close_wait状态。此时客户端已经没有要发送的数据了,但仍可以接受服务器发来的数据。
- 第三次挥手:server将fin置1,发送一个序列号给client;进入last_ack状态;
- 第四次挥手:client收到服务器的fin后,进入time_wait状态;接着将ack置1,发送一个acknowledge number=序列号 1给服务器;服务器收到后,确认acknowledge number后,变为closed状态,不再向客户端发送数据。客户端等待2*msl(报文段最长寿命)时间后,也进入closed状态。完成四次挥手。
2.2 为什么不能把服务器发送的ack和fin合并起来,变成三次挥手(close_wait状态意义是什么)?
因为服务器收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复ack,表示接收到了断开连接的请求。等到数据发完之后再发fin,断开服务器到客户端的数据传送。
2.3 如果第二次挥手时服务器的ack没有送达客户端,会怎样?
客户端没有收到ack确认,会重新发送fin请求。
2.4 客户端time_wait状态的意义是什么?
第四次挥手时,客户端发送给服务器的ack有可能丢失,time_wait状态就是用来重发可能丢失的ack报文。如果server没有收到ack,就会重发fin,如果client在2*msl的时间内收到了fin,就会重新发送ack并再次等待2msl,防止server没有收到ack而不断重发fin。
msl(maximum segment lifetime),指一个片段在网络中最大的存活时间,2msl就是一个发送和一个回复所需的最大时间。如果直到2msl,client都没有再次收到fin,那么client推断ack已经被成功接收,则结束tcp连接。