3.TCP 协议详解
URG : 表示紧急指针是否有效
ACK : 表示确认号是否有效
PSH : 表示接收端应用程序应该立即从 tcp 接收缓冲区读走数据,为接收后续数据腾出空间
RST : 表示要求对方重新建立连接,我们称携带 RST 标志的 tcp 报文段为 复位报文段
SYN : 表示请求建立一个连接,我们称携带 SYN 标志的 tcp 报文段为同步报文段
FIN : 表示通知对方本端要关闭连接了。我们称携带 FIN 标志的 tcp 报文段为结束报文段
半关闭状态:
tcp 连接是全双工的,所以它允许两个方向的数据传输被独立关闭。
服务器和客户端应用程序判断对方是否已经关闭连接的方法是:read 系统调用返回0.
孤儿连接:
客户端执行半关闭后,未等待服务器关闭连接就强行退出了。此时客户端连接由内核来接管,可称之为孤儿连接。
time_wait 状态:
在这个状态,客户端连接要等待一段长为 2MSL(Maximum Segment Life,报文段最大生存时间),才能完全关闭。
MSL 是 tcp 报文段在网络中农的最大生存时间,标准建议值是 2min.
time_wait 状态存在的原因有2个:
1.可靠的终止 tcp 连接
2.保证让迟来的 tcp 报文段有足够的时间被识别并丢弃。
第一个原因很好理解,客户端需要停留在某个状态以处理重复收到的结束报文段(即向服务器发送确认报文段),否则客户端将以复位报文段来回应
服务器,服务器以为是个错误。
在 Linux 系统上,一个 tcp 端口不能被同时打开多次(2次以上)。当一个 tcp 连接处于 time_wait 状态时,我们将无法使用该连接
占用着的端口来建立一个新连接。反过来思考,如果不存在 time_wait 状态,则应用程序能够立即建立一个和刚刚关闭的连接相似的连接(这里
说的相似,是指它们具有相同的 ip 地址和端口号)。这个新的,和原来相似的连接被称为原来连接的化身,新的化身可能收到属于原来连接的,携带
应用程序数据的 tcp 报文段(迟到的报文段),这显然是不应该发生的。这就是 time_wait 状态存在的第二个原因。
另外,因为 tcp 报文段的最大生存时间是 MSL,所以坚持 2MSL 时间的 time_wait状态能够确保网络上2个传输方向上尚未被接收到的,迟到的
tcp 报文段都消失(被中转路由器丢弃)。因此,一个连接的新的化身可以在 2MSL时间之后安全的建立,而绝对不会接收到属于原来连接的应用程序,这就是
time_wait 状态要持续 2MSL 时间的原因。
有时候我们希望避免 time_wait 状态,因为当程序退出之后,我们希望能够立即重启它。但由于处在 time_wait 状态的连接还占用着端口,所有程序无法启动。
但如果是服务器主动关闭连接后异常终止,则因为它总是使用一个知名服务端口号,所以连接的 time_wait 状态将导致它不能立即重启。不过,我们可以通过socket
选项 SO_REUSEADDR 来强制进程立即使用处于 time_wait 状态的连接占用的端口。
复位报文段:
在某些特殊情况下,tcp 连接的一端会向另外一段发送 RST 标志的报文段,即复位报文段,以通知对方关闭连接或重建连接。
1.访问不存在的端口
复位报文段的接收通告窗口大小为0,所以可以预见:收到复位报文段的一端应该关闭连接或者重新连接,而不能回应这个复位报文段。
实际上,当客户端程序向服务器的某个端口发起连接,而该端口仍被处于 time_wait 状态的连接所占用,客户端程序也将收到复位报文段。
2.异常终止连接
tcp 提供了异常终止一个连接的方法,即给对方发送一个复位报文段。一旦发送了复位报文段,发送端所有的排队等待发送的数据都将被丢弃。
3.处理半打开连接
服务器(或者客户端)关闭后者异常终止了链接,而对方没有接收到结束报文段,此时,客户端(或服务器)还维持着原来的连接,而服务器(或客户端)即使重启了,
也已经没有该连接的任何信息了。我们将这种状态称为半打开状态,处于这种状态的连接称为半打开连接。如果客户端(或服务器)往处于半打开状态的连接写入数据,
则对方将回应一个复位报文段。
带外数据:
有些传输层协议具有带外(out of band,OOB)数据的概念,用于迅速通知对方本端发生的重要事情。因此,带外数据比普通数据(也称带内数据)有更高的优先级,它应该
总是立即被发送,而不论发送缓冲区中是否有排队等待发送的普通数据。带外数据的传输可以使用一条独立的传输层连接,也可以映射到传输普通数据的连接中。
udp 没有实现带外数据传输,tcp也没有真正的带外数据。不过 tcp 利用其头部中的紧急指针标志和紧急指针两个字段,给应用程序提供了一种紧急方式。
假设一个进程已经往某个 tcp 连接的发送缓冲区写入了 N 个字节的普通数据,并等待发送。在数据被发送之前,该进程又向这个链接写入了3个字节的带外数据'abc'。此时,
待发送的tcp 报文段的头部被设置 URG 标志,并且紧急指针被设置为指向最后一个带外数据的下一个字节。
超时重传:
tcp 服务必须能够重传超时时间内未收到的确认的 tcp 报文段。为此,tcp 模块为每个tcp报文段都维护一个重传定时器,该定时器在 tcp 报文段第一次被发送时启动。如果
超时时间内未收到接收方的应答,tcp 模块将重传 tcp 报文段并重置定时器。至于下次重传的超时时间如何选择,以及最多执行多少次重传,就是 tcp 的重传策略了。
拥塞控制:
慢启动
拥塞避免
快重传
快恢复
3.1 TCP 服务特点
3.2 TCP 头部结构
3.2.3 使用 tcpdump 观察 TCP 头
3.3 TCP 连接的建立与关闭
3.3.2 半关闭状态
3.3.3 连接超时
3.4 TCP 状态转移
3.4.2 TIME_WAIT 状态
3.5 复位的报文段
3.6 TCP 交互数据流
3.7 TCP 成块数据流
3.8 带外数据
3.9 TCP 超时重传
3.10 拥塞控制