头部信息
TCP首部存储的数据和建立连接有关,具体每个字段的用途可以参考这一篇文章,其中序号和确认号决定了发送数据的内容。
- 头部中间部分"保留"和"窗口"中间是标志位,会携带一些连接的信息
- 序号(Sequence Number):当前TCP数据部分的第一个字节编号(实际是一个非常大的值,非常大的值 - 固定值 = 小的编号,同一请求有一个固定值,固定值来源于建立连接时seq=0时)
- 确认号(Acknowledgment Number):ACK=1时才有效,期望对方下一次传过来的TCP数据部分的第一个字节编号
三次握手
建立连接的时候会有三步,也就是我们所说的三次握手。
- SYN=1,ACK=0,序号 seq=x(连接之初的客户端固定值,简单来说就是0),没有发任何字节,所以数据长度为0,此时是客户端向服务器发送的建立连接请求。
- SYN=1,ACK=1,序号 seq=y(连接之初的服务器固定值,简单来说就是0),确认号 ack = x+1,数据长度为0,此时是服务器向客户端发送响应,表示希望收到客户端发送第1个字节的数据。
- SYN=0,ACK=1,序号 seq=x+1,确认号 ack=y+1,数据部分长度为0,此时客户端确认收到服务器的确认消息,建立连接完成。表示希望收到服务器第一个字节的数据。
连接时,存在一些状态的变化
- CLOSED:client处于关闭状态
- LISTEN:server处于监听状态,等待client连接
- SYN-RCVD:表示server接受到了SYN报文,当收到client的ACK报文后,它会进入到ESTABLISHED状态
- SYN-SENT:表示client已发送SYN报文,等待server的第2次握手
- ESTABLISHED:表示连接已经建立
抓包数据来看如下所示
疑问
那么可能有人会问,为什么需要三次握手,两次不就可以互相确认了吗?
三次握手的目的:防止server端一直等待,浪费资源。
如果只有两次握手,第一次发送SYN=1时因网络延迟没发送成功,那么客户端会再发送一次SYN=1的建立请求,此时发送成功,客户端和服务器之间完成通信。
过了一段时间,第一次发送的SYN=1消息才发送到服务器,此时服务器以为是新的建立连接过程,又会回复一个SYN=1,ACK=1的响应。
如果只有两次连接,服务器会以为成功建立连接,但实际上客户端的数据已经获取到,不会再发送请求了,服务器就会处于一直等待的状态。
采用三次握手就可以防止这样的情况,因为第三次请求没发送给服务器,所以它处于同步已接受状态,如果一直没有收到第三条请求则会关闭连接。
那如果第三次握手失败了呢?
此时server的状态为SYN-RCVD,若等不到client的ACK,server会重新发送SYN+ACK包。如果server多次重发SYN+ACK都等不到client的ACK,就会发送RST包,强制关闭连接。
数据传输
当获取连接后,就可以开始真正的传输数据啦
- 服务器发送第一条请求给客户端,SYN=0,ACK=1,seq=1,ack=583,len=1280,发送数据的序号从1开始,希望对方发送数据从583字节开始。
- 服务器发送第二条请求给客户端,,SYN=0,ACK=1,seq=1281,ack=583,len=2560,因为上一次请求发送了1280字节的数据,所以此条数据从1281开始,还没有收到客户端的数据,所以确认号仍然为583。
- 服务器发送第三条请求给客户端,SYN=0,ACK=1,seq=3841,ack=583,len=1280,到上一次请求的数据已经发送到了1280+2560,所以此次从3841字节的数据开始。
- 客户端回应服务器发送的请求,SYN=0,ACK=1,seq=583,ack=3841,len=0,因为服务器希望收到583字节开始的数据,所以这里序号为583,确认号为3841,希望收到对方以3841开始的数据(这里可能上一条数据还没有收到),长度为0表示只是确认收到的响应。
到这里就是完整的【建立连接】,以及发送请求流程。关于【释放连接】,会在下一篇文章中描述。
以上就是关于 从序号和确认号理解TCP三次握手
的内容 , 更多有关 前端
、网络协议
的内容可以参考我其它的博文,持续更新中~