TCP三次握手和四次挥手的理解


一、TCP三次握手


TCP是面向连接的传输协议。这里所谓的连接,并不是网络上传输的连接,而是通信双方在维护着一个“连接状态”,看上去好像有连接一样。因此,去了解tcp的状态变换是蛮重要的,先理解下3次握手的过程。

如下图

TCP三次握手和四次挥手的理解_第1张图片


客户端主动连接服务端。

(1)第一次握手,客户端打开SYS_SENT,给服务器发送一个SYN连接,随机序列号为J,等待服务器确认,此时客户端为SYS_SENT状态。

(2)第二次握手,服务端收到客户端的SYS J主动要求连接)之后,回复一个意向连接(我也想跟你连接的意思SYN K(SYN连接,随机序列号为K),以及回复确认号,即ACK J+1(我已经收到你想连接我的序列号J,现在我回复确认号,即J+1),服务端进入SYN_RCVD状态。

(3)第三次握手,客户端收到服务端发来的SYN K,ACK J+1,客户端马上进入ESTABLISHED状态,也就是说,服务端确认已经收到我刚才发过去的连接请求啦,现在也要求跟我连接,现在我应该给服务端回复他的想跟我连接的请求,说明他的想跟我连接的请求,我也收到了,即回复ACK K+1,服务端收到后也进入了ESTABLISHED状态。

(4)双方都进入了ESTABLISHED状态,三次握手完成,建立了连接状态,就可以互相通信了。


 ESTABLISHED状态 ESTABLISHED的意思是 建立连接


(5)使用wireshark软件抓包实例

TCP三次握手和四次挥手的理解_第2张图片


二、TCP四次挥手的过程

TCP三次握手和四次挥手的理解_第3张图片



 

客服端和服务端还在通信,都在交换数据Data,都处于established状态。

 

好,现在客户端要跟服务器拜拜,断开连接。

(1)客户端主动要求断开连接,发送FIN J,也就是说发送一个FIN,序列号为J。此时客户端进入FIN_WAIT_1状态。

(2)服务端收到客户端发来的FIN J,马上先回复确认收到,即回复ACK J+1,序列号要加1,此时,服务端通知自己的进程,问问进程有没有什么东西还要发给客户端,人家就等着关闭了。服务器把剩下想发送的数据发过去,如果没有就当然不发了。

 

客户端收到ACK J+1之后,进入另外一个状态FIN_WAIT_2,这个状态就是等着服务器发个也要跟我(客户端)说拜拜的信号,FIN

 

(3)服务端把该发的数据传送完了,这次真的要跟客户端说拜拜了,进入CLOSE_WAIT状态,发个FIN K,序列号为K,此时客户端终于等来了服务端的FIN,结束FIN_WAIT_2状态。

(4)客户端回给服务端ACK K+1,意思是收到你的FIN啦,现在发个回复确认。客户端此时进入2MSL(报文时间)计时等待,关闭连接(CLOSED),而服务端收到最后一个ACK之后,进入LAST_ACK状态,然后马上关闭连接(CLOSED)。

 

 挥手抓包实例:

192.168.1.101是客户端



2MSL的时间是多长?

MSLMaximum Segment Lifetime英文的缩写,中文可以译为“报文最大生存时间”,他是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。因为tcp报文(segment)是ip数据报(datagram)的数据部分,具体称谓请参见《数据在网络各层中的称呼》一文,而ip头中有一个TTL域,TTL是time to live的缩写,中文可以译为“生存时间”,这个生存时间是由源主机设置初始值但不是存的具体时间,而是存储了一个ip数据报可以经过的最大路由数,每经过一个处理他的路由器此值就减1,当此值为0则数据报将被丢弃,同时发送ICMP报文通知源主机。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。

    2MSL即两倍的MSLTCPTIME_WAIT状态也称为2MSL等待状态,当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间,等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。

    TTLMSL是有关系的但不是简单的相等的关系,MSL要大于等于TTL

 

 

为什么客户端发送最后一个ack之后要计时等待?

 

1、为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。

2、他还可以防止已失效的报文段。客户端在发送最后一个ACK之后,再经过经过2MSL,就可以使本链接持续时间内所产生的所有报文段都从网络中消失。从保证在关闭连接后不会有还在网络中滞留的报文段去骚扰服务器。

注意:在服务器发送了FIN-ACK之后,会立即启动超时重传计时器。客户端在发送最后一个ACK之后会立即启动时间等待计时器。

 

 

为什么tcp连接的时候是三次握手,关闭的时候却是四次握手?


在连接时,当服务端收到客户端端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。

关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端端,"你发的FIN报文我收到了",但“我看看我还有什么东西要发送”。只有等到我服务端端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。



你可能感兴趣的:(网络编程,Unix高级环境编程)