最近在看『浏览器从输入网址到页面展示发生了什么』,然后过程中涉及到了建立TCP链接和断开TCP链接的过程,所以单独再补习一下TCP相关的计算机网络知识。
一、TCP是什么?
TCP
是一个面向连接的、可靠的、基于字节流的传输层通信协议。
- 面向连接
(connection-oriented)
:面向连接的协议要求正式发送数据之前需要通过「握手」建立一个逻辑连接,结束通信时也是通过有序的四次「挥手」来断开连接。 - 无连接
(connectionless)
:无连接的协议则不需要「握手」和「挥手」
TCP/IP
协议族
TCP/IP
协议族不仅仅是TCP
、IP
这两种协议,实际上TCP/IP
协议族指的是在IP
协议通信过程中用到的协议的统称。
其中常见到的协议:
IP
:因特网互联协议FTP
:文件传输协议HTTP
:超文本传输协议
分层模型
TCP/IP
协议分为4层:应用层、传输层、网络层、网络接口层
OSI
分为7层:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
二、TCP
头部详解
TCP
固定头部20
字节,IP固定头部20
字节,TCP
头部最长可以达到60
字节。
-
TCP
端口号TCP
的链接需要四个要素确定唯一链接:源IP
,源端口号 + 目的IP
,目的端口号TCP
首部预留了2个16位作为端口号的存储,而IP
地址由上一层IP
协议负责传递。 -
TCP
序号和确认号- 32位序号
seq
:TCP
通信过程中某一个传输方向上的字节流的每个字节的序号,通过这个来确认发送的数据有序。 - 32位确认号
ack
:TCP
对上一次seq
序号做出的确认号,用来响应TCP
报文段,给收到的TCP
报文段的序号seq
加1。
- 32位序号
-
TCP
标志位SYN
:同步标志位,用于建立会话连接,同步序列号ACK
:确认标志位,对已接收的数据包进行确认FIN
:完成标志位,表示我已经没有数据要发送了,即将关闭连接
三、TCP的三次握手
三次握手是指建立一个
TCP
连接时,需要客户端和服务器之间总共发送3个报文。
初始时客户端处于closed
的状态,服务端处于listen
状态。
-
第一次握手
客户端将
TCP
报文标志位SYN
置为1,随机产生一个序号值seq=J
,保存在TCP
首部的序列号(Sequence Number)
字段里,指明客户端打算连接的服务器的端口,并将数据包发送给服务器端,发送完毕后,客户端进入SYN_SENT状态,等待服务器确认。 -
第二次握手
服务器端收到数据包后,由标志位
SYN=1
知道客户端请求建立链接,服务器端将TCP
报文标志位SYN
和ACK
都置为1
,ack=J+1
,随机产生一个序号值seq=K
,并将该数据包发送给客户端以确认链接请求,服务端进入SYN_RCVD状态。 -
第三次握手
客户端收到确认后,检查
ack
是否为J+1
,ACK
是否为1
,如果正确则将标志位ACK
置为1
,ack=K+1
,并将该数据包发送给服务器端,服务器检查ack
是否为K+1
,ACK
是否为1
,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED
状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。
注:ack
和ACK
是不同的概念
ack (Acknowledge number)
,代表头部的确认号,是对上一个包的序号进行确认的号,ack=seq+1
。ACK
:是TCP
的首部标志位,是用于标志TCP
包是否对上一个包进行了确认操作,如果确认,则ACK
为1。
为什么要三次握手?
谢希仁版《计算机网络》中的例子
- 假设
client
发出的第一个连接请求报文段并没有丢失,而是在某个网络节点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server
。 - 本来这是一个早已失效的报文段。但
server
收到此失效的连接请求报文段后,就误认为是client
再次发出的一个新的连接请求。于是就向client
发出确认报文段,同意建立连接。 - 假设采用两次握手,只要
server
发出确认,新的连接就建立了。 - 但由于现在
client
并没有发出建立连接的请求,因此不会理睬server
的确认,也不会向server
发送数据。但server
却以为新的运输连接已经建立,并一直等待client
发来数据。这样,server
的很多资源就白白浪费掉了。 - 而采用"三次握手"的办法可以防止上述现象发生。像刚才那种情况,
client
不会向server的确认发出确认。server
由于收不到确认,就知道client
并没有要求建立连接。
四、四次挥手关闭连接
TCP
链接是全双工的,因此,每个方向都必须要单独进行关闭。
挥手请求可以是Client
端发起,也可以是Server
端发起的,我们假设是Client
端发起。
-
第一次挥手
Client
端发送标志位FIN
和序号seq
给Server
端,此时Client
进入FIN_WAIT_1
状态,表示Client
没有数据要发给Server
端了,希望关闭连接。 -
第二次挥手
Server
端收到FIN
后,回复标志位ACK
和确认号ack
给客户端,此时Client
端进入FIN_WAIT_2
状态,表示Server
端已经收到Client
端的关闭请求。 -
第三次挥手
Server
端发送标志位FIN
给Client
端,此时Client
端进入LAST_ACK
状态,表示服务端数据发送结束,可以关闭链接了。 -
第四次挥手
Client
端收到Server
端发送的FIN
后,回复标志位ACK
给Server
端,此时Client
端进入TIME_WAIT
状态。Server
端收到ACK
后,就立即关闭连接了。Client
端则等待2MSL
的时间后,没有收到回复,则证明Server
端已正常关闭,Client
便也关闭连接。