Java-TCP三握手和四挥手

三握手:
  1.第一次握手:
    客户端A向服务器B发送TCP包,
    其中SYN位(Synchronize)为1,
    并生成一个随机数x写在Seq字段(Sequence number);
    
    A进入SYN_SENT状态。


  2.第二次:
    B收到A的TCP包后,向A发送一个TCP包表示确认,
    其中SYN位为1,ACK位(acknowledge)为1,
    ack字段(acknowledge number)为x+1,
    并生成一个随机数y写在Seq字段(Sequence number);
    
    B进入SYN_RECV状态。


  3.第三次:
    A收到B的TCP包,又要发送一个TCP包来确认,
    其中SYN位设为0,ACK位设为1,
    并将ack设为y+1;
    
    A和B都进入ESTABLISH状态,成功建立连接。


  4.注意:大写的为标志位,如ACK,SYN,占1位。
         而ack占4个字节,Seq占4个字节。
    

位含义:
在这里插入图片描述
图解:
在这里插入图片描述

实例:
在这里插入图片描述

四挥手:
  1.第一次挥手:
    客户端A发送一个TCP包,其中FIN位设为1,
    并且Seq字段的值设为 前面传输的数据 的最后一个字节 的序号+1,假设为u。
    
    A进入FIN_WAIT_1状态。(终止等待1)

  2.第二次:
    服务器B收到A的FIN包后,要发送一个TCP包表示确认收到,
    其中ACK位为1,ack设为u+1,
    由于TCP为全双工,两边都发数据,所以传输的数据 的最后一个字节 的序号+1
    写在Seq字段(Sequence number),假设为v;

    B进入CLOSE_WAIT状态。(停止等待)
    A收到后,进入FIN_WAIT_2状态。(终止等待2)
  
  
  3.第三次:
    服务器B发送完最后的数据,
    再次发送FIN包,(前面发送是确认,这次是请求停止,为何不一起,看面试题)
    其中FIN=1,ACK=1,
    ack和上面发的一样,为u+1,
    而这段时间又发了数据,所以Seq字段为最后字节序号+1,假设为w;

    B进入LAST_ACK状态。(最后确认).


  4.第四次:
    A收到B的FIN包,需发送一个TCP包以表示确认,
    其中ACK=1,ack=w+1,
    由于A先发送FIN包,证明A不发送消息了,则Seq字段用前面发的u+1即可。
    

在这里插入图片描述

常见面试题
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?

1.答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

2.这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的连接请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可能未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

【问题3】为什么不能用两次握手进行连接?

答:3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

现在把三次握手改成仅需要两次握手,死锁是可能发生的。
作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,
S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,
S认为连接已经成功地建立了,可以开始发送数据分组。
可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,
不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。
在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,
只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。
这样就形成了死锁。

【问题4】如果已经建立了连接,但是客户端突然出现故障了怎么办?

TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75s发送一次。若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

【问题5】TCP协议和UDP协议的区别是什么
1.TCP协议是有连接的,有连接的意思是开始传输实际数据之前TCP的客户端和服务器端必须通过三次握手建立连接,会话结束之后也要结束连接。而UDP是无连接的
2.TCP协议保证数据按序发送,按序到达,提供超时重传来保证可靠性,但是UDP不保证按序到达,甚至不保证到达,只是努力交付,即便是按序发送的序列,也不保证按序送到。
3.TCP协议所需资源多,TCP首部需20个字节(不算可选项),UDP首部字段只需8个字节。
4.TCP有流量控制和拥塞控制,UDP没有,网络拥堵不会影响发送端的发送速率
5.TCP是一对一的连接,而UDP则可以支持一对一,多对多,一对多的通信。
6.TCP面向的是字节流的服务,UDP面向的是报文的服务。

面试题原文:
https://blog.csdn.net/qq_38950316/article/details/81087809
参考:
https://www.cnblogs.com/zmlctt/p/3690998.html
https://cloud.tencent.com/info/47be7829f802a6edca6e834720e12d95.html
https://wenku.baidu.com/view/01fdda83e53a580216fcfee6.html

猜你喜欢

转载自blog.csdn.net/weixin_41227335/article/details/87933833