TCP协议的一些问题

1 连接握手三次

解释1:已失效的连接请求报文段

情况下如下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

解释2:

这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题,  无论你在消息中包含什么信息, 三次通信是
理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的. 请注意这里的本质需求,
信道不可靠, 数据传输要可靠.

0次: 显然不行
1次: A->B, A不知道B是否同意
2次: A->B, B->A. B不知道A是否收到自己的消息, 因为信道不完全可靠
3次: A->B, B->A, A->B. 两边都收到了对方的ACK, 意味着各自都了解了对方的意图, 从而可以对是否开始通信这个最简单的问题
达成一致.

2 断开四次

解释:

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

3 为什么说TCP是可靠连接

(1) 连接是对状态的保持,实际上就是在客户端和服务器端都维护一个变量,这个变量维护现在数据传输的状态,例如传输了哪些数据,下一次需要传输哪些数据,等等,并不是真的我们想象中的真的有什么东西连接着这两端,因为无论对于有连接还是无连接,都有网线连着呢(不包括无线网),所以连接根本就不是是否真的有什么东西把他们连接起来,真实的含义就是我上面说的,两边维护一个状态变量。

(2) UDP通讯有四个参数:源IP、源端口、目的IP和目的端口。而TCP通讯至少有有六个参数:源IP、源端口、目的IP和目的端口,以及序列号(SYN)和应答号(ACK)。(SYN为己方发的,ACK则是回应对方的。ACK=对方的SYN+1,意思是我已经收到SYN,需要你下次发送SYN+1)

序列号和应答号是TCP通讯特有的参数,TCP通讯利用序列号和应答号来保持和确认数据的关联与正确性,是在三次握手中确定的,不正确的序列号和应答号会导致无法正常通讯。因此对TCP连接的连接概念可以简单理解成为同UDP通讯相比,用序列号和应答号确定了相互之间的连接特征,来保证数据传输的正确性。

(3)TCP采用超时重传的机制来确保数据传输到对方。

4 为什么TCP四次分手中,主动关闭方最后为什么要等待2MSL之后才关闭连接

(1)保证TCP协议的全双工连接能够可靠关闭

如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

(2)保证这次连接的重复数据段从网络中消失

如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

上一篇:Java中Overload和Override的区别


下一篇:Java对象转JSON时如何动态的增删改查属性