为什么需要三次握手?
答:三次握手的目的是“为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误”,这种情况是:一端(client)A发出去的第一个连接请求报文并没有丢失,而是因为某些未知的原因在某个网络节点上发生滞留,导致延迟到连接释放以后的某个时间才到达另一端(server)B。本来这是一个早已失效的报文段,但是B收到此失效的报文之后,会误认为是A再次发出的一个新的连接请求,于是B端就向A又发出确认报文,表示同意建立连接。如果不采用“三次握手”,那么只要B端发出确认报文就会认为新的连接已经建立了,但是A端并没有发出建立连接的请求,因此不会去向B端发送数据,B端没有收到数据就会一直等待,这样B端就会白白浪费掉很多资源。如果采用“三次握手”的话就不会出现这种情况,B端收到一个过时失效的报文段之后,向A端发出确认,此时A并没有要求建立连接,所以就不会向B端发送确认,这个时候B端也能够知道连接没有建立。
问题的本质:信道是不可靠的,但是我们要建立可靠的连接发送可靠的数据,也就是数据传输是需要可靠的。在这个时候三次握手是一个理论上的最小值,并不是说是tcp协议要求的,而是为了满足在不可靠的信道上传输可靠的数据所要求的。
为什么需要四次挥手?
先了解什么是TCP的socket编程中“全双工的字节流”?
全双工:意味着TCP的收发是可以同时进行的。即接收的时候可以发送,发送的时候也可以接收,两者互不冲突,可同时进行。
字节:意味着,无论物理层或链路层收到的数据是否为一个个二进制位的数据,在TCP层接收到的数据一定是一个个字节。也就是说,我们在进行socket编程时,只需要考虑接收一个个字节,而不是一个个位的数据。
流:意味着,socket的数据无头无尾,就像流水一样,如果从中间任意位置起,你无法知道一个消息包确切的开始或结束位置,除非从TCP的头开始算起。
答:
tcp是全双公的,要实现可靠的连接关闭,A发出结束报文FIN,收到B确认后A知道自己没有数据需要发送了,B知道A不再发送数据了,自己也不会接收数据了,但是此时A还是可以接收数据,B也可以发送数据;当B发出FIN报文的时候此时两边才会真正的断开连接,读写分开。
四次挥手牵扯到的状态装换。
- ** FIN_WAIT_1 ** 表示在等待另一方的FIN报文,和FIN_WAIT_2的区别是,FIN_WAIT_1表示socket现在要主动关闭连接,在发送完FIN报文后socket进入FIN_WAIT_1状态,当收到另一方发送FIN的ACK之后立即进入FIN_WAIT_2状态;
- ** FIN_WAIT_2 ** 同上,此时需要做的事情是可能还会接收数据,然后等待另一方的FIN;
- ** TIME_WAIT ** 存在主动关闭的一方,表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL(Max Segment Lifetime))后即可回到CLOSED可用状态了,需要等一段时间时原因是网络是不可靠的,不能保证这个ACK发送成功了,如果失败了,对端会超时重传FIN;
- ** CLOSING ** 表示在发送FIN之后,没有收到对方的ACK,而是收到了对方的FIN,这中情况很少见,只有在两端几乎同时关闭同一个socket的时候才会出现CLOSING状态;
- ** CLOSE_WAIT ** 表示收到对方的FIN之后,回给对方ACK,此时处于CLOSE_WAIT状态,等待关闭,要看自己是否还有数据要发送;
- ** LAST_ACK ** 表示收到对方的FIN之后,回给对方ACK,然后自己也要关闭发送FIN,等待另一方的ACK时候的状态;
- ** CLOSED ** 这个状态表示连接已经断开。
待补充。。。