我们知道TCP协议是传输层的可靠数据传输协议,它被称为是面向连接的(connection-oriented)协议。而在连接开始的过程中,两个要传输数据的进程需要先相互握手。 之前大概知道TCP三次握手、四次挥手的原理和原因,但是对技术细节却不清楚,今天就在这里查缺补漏一下。
三次握手
用大白话解释就是两个人打电话:
客户:你好(第一次握手,仅打招呼不说事)
服务器:你好(第二次握手,给对方回应,我听得见你)
客户:你好你好,我这里有个东西...(第三次握手,确认可以收到对方回应,然后开始说正事也就是发送数据)
那么在技术细节上,该如何理解呢?这就得先从TCP报文结构看起:
可以看到在三次握手中主要用到了下面四个报文字段
- 序号(seq)32bit
- 确认号(ack)32bit
上面两个字段被TCP发送方和接收方用来实现可靠数据传输服务。
序列号和确认号原理。
TCP把数据看成一个无结构的、有序的字节流。例如数据流由500000字节的文件组成,其MSS(MaximumSegmentSize)为1000字节,则TCP将该文件分解成500个报文段。给首个报文段分配序号0,第二个报文段分配序号1000,剩下的序列号以此类推。(在实际使用中首序号一般都是随机分配)
确认号:主机A填充进报文段的确认号是主机A期望从主机B收到的下一字节的序号。例如上面首个报文段的序号是0,那么返回来报文段确认号就应该是1000,因为主机B期望下个收到的报文段序号是1000。
上面就是序号seq和确认号ack的作用。 - SYN 1bit 用于发起连接信号。
- ACK 1bit 用于指示确认字段中的值是有效的,即该报文段包括一个对已被成功接收报文段的确认。
- FIN 1bit 用于断开连接信号。
三次握手的详细过程
- 第一次握手,客户端首先向服务器发送一个特殊的TCP报文段。这个报文段中的SYN标志位被置为1,同时序号seq被存入一个随机的初始序号client_isn。并不包含应用层数据。所以此报文段被称为TCPSYN报文段。
- 当服务器接收到客户发送来的TCPSYN报文段后,服务器会为该TCP连接分配缓存和变量,然后向客户端发送允许连接的报文段。在这个报文段中,SYN也被置为1,ACK被置为1,序号seq是服务器随机生成的一个初始序列号server_isn。和TCPSYN报文段不同的是,这里需要在确认号ack字段中存入client_isn+1。此报文被称为SYNACK报文段。
- 当客户端接收到服务器的SYNACK报文段后,也会为这个TCP连接分配缓存和变量,并且开始第三次握手,也是最后一次。本次握手确认了来自服务器的连接确认,将SYN置为0,ACK置为1,序号seq为client_isn+1,确认号ack为server_isn+1。并且此报文可以携带应用层数据。至此,整个TCP建立连接的三次握手就全部完成了。
四次挥手
三次握手是建立连接,而四次挥手就是断开连接了。我们也先用大白话版来解释一下:
客户:我挂电话了啊
服务器:哎哟,等会等会,我看看有没有啥忘了的。
服务器:好了好了,你挂了吧
客户:得嘞
而从技术细节上看则是这样
- 客户向服务器发送一个报文段,其中的FIN比特位被置为1,代表我要断开连接。
- 服务器发送一个ACK比特位被置为1的确认报文段。
- 等待服务器处理结束后再向客户发送一个FIN被置为1的报文段,确认断开连接。
- 客户回复一个ACK为1的确认报文段。连接断开。
参考资料:
《计算机网络:自顶向下》
理解TCP