golang:三次握手四次挥手总结

TCP的三次握手

所谓三次握手 Three-Way Handshake 是指创建一个TCP链接时,须要客户端和服务端总共发送3个包以确认链接的创建。比如两我的在打电话:tcp

当链接被创建或被终止,交换的报文段只包含TCP头部,而没有数据。指针

tcp报文头部结构

  • 序号:seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
  • 确认序号:ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,确认方ack=发起方seq+1,两端配对。
  • 标志位
    • ACK:确认序号有效。
    • FIN:释放一个链接。
    • RST:重置链接。
    • SYN:发起一个新链接。
    • PSH:接收方应该尽快将这个报文交给应用层。
    • URG:紧急指针(urgent pointer)有效。

    第一次握手:客户端要向服务端发起链接请求,首先客户端随机生成一个起始序列号ISN(好比是100),那客户端向服务端发送的报文段包含SYN标志位(也就是SYN=1),序列号seq=100。code

    第二次握手:服务端收到客户端发过来的报文后,发现SYN=1,知道这是一个链接请求,因而将客户端的起始序列号100存起来,而且随机生成一个服务端的起始序列号(好比是300)。而后给客户端回复一段报文,回复报文包含SYN和ACK标志(也就是SYN=1,ACK=1)、序列号seq=300、确认号ack=101(客户端发过来的序列号+1)。blog

    第三次握手:客户端收到服务端的回复后发现ACK=1而且ack=101,因而知道服务端已经收到了序列号为100的那段报文;同时发现SYN=1,知道了服务端赞成了此次链接,因而就将服务端的序列号300给存下来。而后客户端再回复一段报文给服务端,报文包含ACK标志位(ACK=1)、ack=301(服务端序列号+1)、seq=101(第一次握手时发送报文是占据一个序列号的,因此此次seq就从101开始,须要注意的是不携带数据的ACK报文是不占据序列号的,因此后面第一次正式发送数据时seq仍是101)。当服务端收到报文后发现ACK=1而且ack=301,就知道客户端收到序列号为300的报文了,就这样客户端和服务端经过TCP创建了链接。请求

四次挥手

    好比客户端初始化的序列号ISA=100,服务端初始化的序列号ISA=300。TCP链接成功后客户端总共发送了1000个字节的数据,服务端在客户端发FIN报文前总共回复了2000个字节的数据。im

    第一次挥手:当客户端的数据都传输完成后,客户端向服务端发出链接释放报文(固然数据没发完时也能够发送链接释放报文并中止发送数据),释放链接报文包含FIN标志位(FIN=1)、序列号seq=1101(100+1+1000,其中的1是创建链接时占的一个序列号)。须要注意的是客户端发出FIN报文段后只是不能发数据了,可是还能够正常收数据;另外FIN报文段即便不携带数据也要占据一个序列号。数据

    第二次挥手:服务端收到客户端发的FIN报文后给客户端回复确认报文,确认报文包含ACK标志位(ACK=1)、确认号ack=1102(客户端FIN报文序列号1101+1)、序列号seq=2300(300+2000)。此时服务端处于关闭等待状态,而不是立马给客户端发FIN报文,这个状态还要持续一段时间,由于服务端可能还有数据没发完。客户端

    第三次挥手:服务端将最后数据(好比50个字节)发送完毕后就向客户端发出链接释放报文,报文包含FIN和ACK标志位(FIN=1,ACK=1)、确认号和第二次挥手同样ack=110二、序列号seq=2350(2300+50)。img

    第四次挥手:客户端收到服务端发的FIN报文后,向服务端发出确认报文,确认报文包含ACK标志位(ACK=1)、确认号ack=235一、序列号seq=1102。注意客户端发出确认报文后不是立马释放TCP链接,而是要通过2MSL(最长报文段寿命的2倍时长)后才释放TCP链接。而服务端一旦收到客户端发出的确认报文就会立马释放TCP链接,因此服务端结束TCP链接的时间要比客户端早一些。di