三次握手
三次握手是建立连接的过程,四次挥手是断开连接的过程,三次握手发生在socket.accept()之前。
客户端和服务器尝试建立连接的时候服务器就会和客户端进行一系列的数据交换称为握手,这个过程建立完了后,连接就好了。
A和B完成建立连接的过程需要3次打招呼的数据交互。
三次握手是一种可靠性的机制。
tcp想要保证可靠性传输,可靠传输的前提是网络路径得通畅,tcp三次握手就是验证网路通信时候否通畅,以及验证每个主机发送能力和接收能力是否正常。
当我和女朋友连麦打游戏时得先验证麦克风和耳机是否正常。
第一次我发送喵喵喵,为了验证我的麦克风是否正常,也是在验证女朋友耳机是否正常,女朋友收到喵喵喵,他就知道我的麦克风和他的耳机是好的。
第二次女朋友发送喵喵,为了验证他的麦克风是否正常,也验证我的耳机收否正常,我收到喵喵,我就知道我的耳机是好的,他的麦克风也是好的。
第三次我发送喵。就是对上述的喵喵进行回应,他收到喵说明刚才他发的喵喵我收到了。也就意味着双方设备都正常,可以互相通信了。
三次握手为什么是三次呢?因为恰好3次就能验证双方的发送能力和接收能力是否正常,并且把这样的信息同步给双方。
四次是否可以?可以但是没有必要。
消息协商
三次握手还能起到消息协商的效果。通信的时候涉及到一些参数,需要双方保持一致,通过协商来确定具体的参数是多少。
Tcp通信过程中有很多信息需要协调,比如双方的序号从几开始(一般不会从0或者1开始),这样做主要是保证2次连接消息的序号能有较大的差异,从而判定出某个消息是否属于这个连接的。网路上传输的信息可能后发先至,极端情况下,某个信息迟到了很久。当消息到达对端的时候,服务器和客户端已经断开了上一个连接。这是重新建立的连接了。这个时候就可以通过序号,明显的识别出这是上一个连接的信息,就可以丢弃了。
综上三次握手:
1.投石问路。验证通信路径是否通畅,双方的发送接收能力是否正常。
2.协商必要的参数。使客户端和服务器使用相同的参数进行消息的传输。
四次挥手
通信过程中,通信双方都在内存中保存了对端的信息,如果不需要连接了就得及时释放上述存储空间。
四次挥手和三次握手非常相似,三次握手必然是客户端主动发起的,四次挥手不一定,服务器也可以主动发起,大多还是客户端发起的。
第一个FIN由内核控制,第二个FIN是应用程序来控制的,调用socket.close();或者结束进程,就会触发FIN,相比之下ACK则是内核控制的,收到FIN就会立马返回ACK。
如果服务器始终不进行close会咋样?客户端始终不关闭吗?当程序执行结束不进行close 操作,此时服务器的tcp状态就处于CLOSE_WAIT状态,此时虽然连接没有关闭,但是此时这个连接已经不能用了。针对当前的socket进行操作,如果数据从缓存区中没有读完,能正常读到。如果读完,此时就会抛出异常。无论如何此时已经不能使用了,关闭是唯一的选择。更严重的是比如代码写出bug了,close就忘记写了,此时站在客户端的角度收不到对方的fin,也会进行等待,等待一定的时间就会放弃连接。
如果重传过程中出现丢包了怎么办?
这里也是超时重传,如果重传多次失败也会单方面放弃连接。如果主机A第二次接收到FIN,并且发出ACK,站在A的角度四次挥手就结束了。如果A发出ACK主机B并没有收到,出现丢包,把A释放了会出现问题,无人能够ACK。因此就需要让A最后一次发出ACK后等待一定的时间,如果没有接到B重新发来的FIN说明没有出现丢包,让A释放掉,如果接收到,让A重新传ACK。
Tcp是如何实现可靠传输的?
确认应答,超时重传,三次握手,四次挥手
三次握手是探路的,一旦网络通畅,双方接收和发送能力正常,三次握手的任务就完成。确认应答才是真正保证每次传输可靠的。