本章介绍了 Internet 传输层的两个重要协议 TCP 和 UDP ,包括这两种协议的报文格式和工作原理。特别地,本章详细介绍了 TCP 的连接建立与关闭,以及连接建立与关闭过程的状态转换。
Internet 在传输层有两种主要的协议:一种是面向连接的协议 TCP ,一种是无连接的协议 UDP 。由于 UDP 基本上是在 IP 的基础上增加一个短的报头而得到的,比较简单,因此本章将先介绍 UDP ,然后再重点介绍 TCP 。
在TCP/IP 协议簇中, IP 提供在主机之间传送数据报的能力,每个数据报根据其目的主机的 IP 地址进行在 Internet 中的路由选择。传输层协议为应用层提供的是进程之间的通信服务。为了在给定的主机上能识别多个目的地址,同时允许多个应用程序在同一台主机上工作并能独立地进行数据报的发送和接收, TCP/UDP 提供了应用程序之间传送数据报的基本机制,它们提供的协议端口能够区分一台机器上运行的多个程序。
也就是说, TCP/UDP 使用 IP 地址标识网上主机,使用端口号来标识应用进程,即 TCP/UDP 用主机 IP 地址和为应用进程分配的端口号来标识应用进程。端口号是 16 位的无符号整数, TCP 的端口号和 UDP 的端口号是两个独立的序列。尽管相互独立,如果 TCP 和 UDP 同时提供某种知名服务,两个协议通常选择相同的端口号。这纯粹是为了使用方便,而不是协议本身的要求。利用端口号,一台主机上多个进程可以同时使用 TCP/UDP 提供的传输服务,并且这种通信是端到端的,它的数据由 IP 传递,但与 IP 数据报的传递路径无关。网络通信中用一个三元组可以在全局唯一标志一个应用进程:
(协议,本地地址,本地端口号)
这样一个三元组,叫做一个半相关( half-association ),它指定连接的每半部分。一个完整的网间进程通信需要由两个进程组成,并且只能使用同一种高层协议。也就是说,不可能通信的一端用 TCP 协议,而另一端用 UDP 协议。因此一个完整的网间通信需要一个五元组来标识:
(协议,本地地址,本地端口号,远地地址,远地端口号)
这样一个五元组,叫做一个相关( association ),即两个协议相同的半相关才能组合成一个合适的相关,或完全指定组成一连接。
端口号的分配是一个重要问题。有两种基本分配方式:第一种叫全局分配,这是一种集中控制方式,由一个公认的中央机构根据用户需要进行统一分配,并将结果公布于众。第二种是本地分配,又称动态连接,即进程需要访问传输层服务时,向本地操作系统提出申请,操作系统返回一个本地唯一的端口号,进程再通过合适的系统调用将自己与该端口号联系起来(绑扎)。 TCP/UDP 端口号的分配中综合了上述两种方式。 TCP/UDP 将端口号分为两部分,少量的作为保留端口,以全局方式分配给服务进程。因此,每一个标准服务器都拥有一个全局公认的端口(即周知口, well-known port ),即使在不同机器上,其端口号也相同。剩余的为自由端口,以本地方式进行分配。表 3-1 列出了常用的 TCP/UDP 周知端口号。
表 3-1 常用周知端口号列表
端口号 |
协议 |
关键词 |
UNIX 关键词 |
描述 |
1 |
TCP |
TCPMUX |
- |
TCP 复用器 |
7 |
TCP/UDP |
ECHO |
echo |
回送 |
9 |
TCP/UDP |
DISCARD |
discard |
丢弃 |
15 |
TCP/UDP |
- |
netstat |
网络状态程序 |
20 |
TCP |
FTP-DATA |
ftp-data |
文件传输协议(数据) |
21 |
TCP |
FTP |
ftp |
文件传输协议 |
22 |
TCP/UDP |
SSH |
ssh |
安全 Shell 远程登录协议 |
23 |
TCP |
TELNET |
telnet |
远程登录 |
25 |
TCP |
SMTP |
smtp |
简单邮件传输协议 |
37 |
TCP/UDP |
- |
time |
时间 |
42 |
TCP/UDP |
NAMESERVER |
name |
主机名字服务器 |
43 |
TCP/UDP |
NICNAME |
whois |
是谁 |
53 |
TCP/UDP |
DOMAIN |
nameserver |
域名服务器 |
67 |
UDP |
BOOTPS |
bootps |
引导协议服务器 |
68 |
UDP |
BOOTPC |
bootpc |
引导协议客户 |
69 |
UDP |
TFTP |
tftp |
简单文件传送协议 |
79 |
TCP |
FINGER |
finger |
Finger |
80 |
TCP |
HTTP |
http |
超文本传输协议 |
88 |
TCP |
KERBEROS |
kerberos |
Kerberos 协议 |
93 |
TCP |
DCP |
- |
设备控制协议 |
101 |
TCP |
HOSTNAME |
hostnames |
NIC 主机名字服务器 |
110 |
TCP |
POP3 |
pop3 |
邮局协议版本 3 |
111 |
TCP/UDP |
SUNRPC |
sunrpc |
Sun Microsystems RPC |
119 |
TCP |
NNTP |
nntp |
USENET 新闻传送协议 |
123 |
UDP |
NTP |
ntp |
网络时间协议 |
139 |
TCP |
NETBIOS-SSN |
- |
NETBIOS 会话协议 |
161 |
UDP |
- |
snmp |
简单网络管理协议 |
162 |
UDP |
- |
snmp-trap |
SNMP 陷阱 |
389 |
TCP |
LDAP |
ldap |
轻量目录访问协议 |
443 |
TCP |
HTTPS |
https |
安全 HTTP 协议 |
513 |
UDP |
- |
who |
UNIX rwho daemon |
514 |
UDP |
- |
syslog |
系统日志 |
525 |
UDP |
- |
timed |
UNIX time daemon |
546 |
TCP |
DHCP-CLIENT |
dhcp-client |
动态主机配置协议客户 |
547 |
TCP |
DHCP-SERVER |
dhcp-server |
动态主机配置协议服务器 |
TCP 是一种有连接的传输服务,它提供可靠的传输,是大部分 Internet 应用的基础。 UDP 提供的是一种无连接服务,每个数据包独立传输,在传统的应用中因为不能像 TCP 那样保证数据的可靠传输而应用较少。但是对于新的实时视频、音频数据的传输来说,因为不能容忍 TCP 重传带来的时延,常常建立在 UDP 之上。 UDP 为互联网上实时视频、音频服务提供了极好的实验环境。
UDP(User Datagram Protocol) 是一个简单的面向数据报的传输层协议,进程的每个输出操作都正好产生一个 UDP 数据报,并组装成一份待发送的 IP 数据报。 UDP 不提供可靠性,它把应用程序传给 IP 层的数据发送出去,但是并不保证它们能到达目的地。应用程序必须关心 IP 数据报的长度。如果它超过网络的 MTU ,那么就要对 IP 数据报进行分片。 RFC 768 [Postel 1980] 是 UDP 的正式规范。
3.2.1 UDP 报文格式
每个 UDP 报文成为一个用户数据报,分 UDP 报头和 UDP 数据区两部分。报头由四个 16 位长的字段组成,分别说明该报文的源端口、目的端口、报文长度以及校验和。 UDP 报文格式如图 3-1 所示。
0 |
16 31 |
UDP 源端口 |
UDP 目的端口 |
UDP 报文长度 |
UDP 校验和 |
数据 |
|
… |
图 3-1 UDP 报文格式
UDP 源端口字段和目的端口字段包含了 16 位的 UDP 协议端口号,表示发送进程和接收进程。 UDP 长度字段指的是 UDP 报头和 UDP 数据的字节长度,该字段的最小值为 8 字节(发送一份 0 字节的 UDP 数据报是可以的)。 UDP 检验和覆盖 UDP 报头和 UDP 数据。 UDP 和 TCP 在报头中都有覆盖它们报头和数据的检验和。 UDP 的检验和是可选的,如果该字段值为 0 表明不进行校验。一般来说,使用校验和字段是必要的。
3.2.2 UDP 的封装与协议的分层
在第 1 章介绍的 TCP/IP 协议层次结构模型中(参见图 1-3 ), UDP 位于 IP 层之上。应用程序访问 UDP 层,然后使用 IP 层传送数据报,如图 3-2 所示。
将 UDP 层放在 IP 层之上,表示一个 UDP 报文在 Internet 中传输时要封装到 IP 数据报中。最后,网络接口层将数据包封装到一个帧中再进行物理传输通道上的传输。封装过程如图 3-3 所示。
概念性层次 |
|
UDP 报头 |
UDP 数据区 |
||
应用 |
|
||||
用户数据报( UDP ) |
|
IP 报头 |
IP 数据区 |
||
互联网( IP ) |
|
||||
网络接口 |
|
帧头 |
帧数据区 |
||
图 3-2 分层模型中的 UDP 层 |
图 3-3 UDP 的封装 |
由图可知, IP 层的报头指明了源主机和目的主机的地址,而 UDP 层的报头指明了主机上的源端口和目的端口。 IP 层和 UDP 层之间的职责是清楚而明确的: IP 层指负责在 Internet 上的一对主机之间进行数据传输,而 UDP 层只负责对一台主机上的复用的多个源端口或目的端口进行区分。
3.2.3 UDP 的复用、分解与端口
UDP 也提供复用和分解的功能。它接收多个应用程序送来的数据报,把它们送给 IP 层区传输,同时它接受 IP 层送来的 UDP 数据报,把它们送给对应的应用程序。
从概念上讲,所有的 UDP 软件与应用程序之间的复用和分解都要通过端口机制来实现。实际上每个应用程序在发送数据报之前必须与操作系统进行协商以获得协议端口和相应的端口号。凡是利用指定的端口发送数据报的应用程序都要把端口号放入 UDP 报文中的源端口字段中。
UDP 的分解操作如图 3-4 所示, UDP 从 IP 层接收了数据报之后,根据 UDP 的目的端口号进行分解操作。
TCP(Transfer Control Protocol) 是专门设计用于在不可靠的 Internet 上提供可靠的、端到端的字节流通信的协议。 Internet 不同于一个单独的网络,不同部分可能具有不同的拓扑结构、带宽、延迟、分组大小以及其它特性。 TCP 被设计成能动态满足 Internet 的要求,并且足以健壮地面对多种出错。 RFC 793 [Postel 1981] 是 TCP 的正式规范。
3.3.1 可靠的数据流传输
UDP 提供的服务是不可靠的数据传送服务,当传送过程中出现差错、网络软件发生故障或网络负载太重时,分组可能会丢失,数据可能被破坏。这就需要应用程序负责进行差错检测和恢复工作,对传输数据量很大的应用来说,采用这种不可靠的数据传输是不合适的。因此需要有一种可靠的数据流传输方法,这就是 TCP 。 TCP 提供的可靠传输服务有如下五个特征:面向数据流:当两个应用程序传输大量数据时,将这些数据当作一个可划分为字
3.3.2 滑动窗口概念
从图 3-5 可以看出,虽然网络具有同时进行双向通信的能力,但由于在接到前一个分组的确认信息之前必须推迟下一个分组的发送,简单的肯定确认协议浪费了大量宝贵的网络带宽。为此, TCP 使用滑动窗口的机制来提高网络吞吐量,同时解决端到端的流量控制。
滑动窗口技术是简单的带重传的肯定确认机制的一个更复杂的变形,它允许发送方在等待一个确认信息之前可以发送多个分组。如图 3-7 所示,发送方要发送一个分组序列,滑动窗口协议在分组序列中放置一个固定长度的窗口,然后将窗口内的所有分组都发送出去;当发送方收到对窗口内第一个分组的确认信息时,它可以向后滑动并发送下一个分组;随着确认的不断到达,窗口也在不断的向后滑动。
图 3-7 (a) 窗口内包括 8 个分组的滑动窗口协议
(b) 收到对 1 号分组的确认信息后,窗口滑动,使得 9 号分组也能被发送
滑动窗口协议的效率与窗口大小和网络接收分组的速度有关。图 3-8 表示了一个窗口大小为 3 的的滑动窗口协议软件的动作示意图。发送方在收到确认之前就发出了三个分组,在收到第一个分组的确认 ACK1 后,又发送了第四个分组。比较图 3-5 和图 3-8 ,就可以看出使用滑动窗口后网络吞吐量的提高。实际上,当窗口大小等于 1 时,滑动窗口协议就等同于简单的肯定确认协议。通过增加窗口大小,可以完全消除网络的空闲状态。在稳定的情况下,发送方能以网络传输分组的最快能力来发送分组。
图 3-8 使用窗口大小为 3 的滑动窗口协议传输分组示例
3.3.3 TCP 报文格式
两台计算机上的 TCP 软件之间传输的数据单元称为报文段。 TCP 通过报文段的交互来建立连接、传输数据、发出确认、通告窗口大小以及关闭连接。 TCP 报文分为两部分,前面是报头,后面是数据。报头的前 20 个字节格式是固定的,后面是可能的选项,数据长度最大为 65535 – 20 – 20 = 65495 字节,其中第一个 20 指 IP 头,第二个 20 指 TCP 头。不带任何数据的报文也是合法的,一般用于确认和控制报文。图 3-9 给出了 TCP 报文的布局格式。每个字段的意义简介如下:
0 |
31 |
|||||||
源端口( source port )号 |
目的端口( destination port )号 |
|||||||
顺序号( sequence number ) |
||||||||
确认号( acknowledgement number ) |
||||||||
TCP 报头长度 |
保留 |
URG |
ACK |
PSH |
RST |
SYN |
FIN |
窗口大小( window size ) |
校验和( checksum ) |
紧急指针( urgent pointer ) |
|||||||
选项+填充( 0 或多个 32 位字) |
||||||||
数据( 0 或多个字节) |
图 3-9 TCP 报头格式
TCP 是一个面向连接的协议,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。本节将详细讨论一个TCP 连接是如何建立的以及通信结束后是如何终止的。
3.4.1 建立一个 TCP 连接
TCP使用三次握手 ( three-way handshake ) 协议来建立连接,图 3-10 描述了三次握手的报文序列。这三次握手为:
发送第一个 SYN 的一端将执行主动打开( active open ),接收这个 SYN 并发回下一个 SYN 的另一端执行被动打开( passive open )。另外, TCP 的握手协议被精心设计为可以处理同时打开( simultaneous open ),对于同时打开它仅建立一条连接而不是两条连接。因此,连接可以由任一方或双方发起,一旦连接建立,数据就可以双向对等地流动,而没有所谓的主从关系。
三次握手协议是连接两端正确同步的充要条件。因为 TCP 建立在不可靠的分组传输服务之上,报文可能丢失、延迟、重复和乱序,因此协议必须使用超时和重传机制。如果重传的连接请求和原先的连接请求在连接正在建立时到达,或者当一个连接已经建立、使用和结束之后,某个延迟的连接请求才到达,就会出现问题。采用三次握手协议(加上这样的规则:在连接建立之后 TCP 就不再理睬又一次的连接请求)就可以解决这些问题。
三次握手协议可以完成两个重要功能:它确保连接双方做好传输准备,并使双方统一了初始顺序号。初始顺序号是在握手期间传输顺序号并获得确认:当一端为建立连接而发送它的 SYN 时,它为连接选择一个初始顺序号;每个报文段都包括了顺序号字段和确认号字段,这使得两台机器仅仅使用三个握手报文就能协商好各自的数据流的顺序号。一般来说, ISN 随时间而变化,因此每个连接都将具有不同的 ISN 。
3.4.2 关闭一个 TCP 连接
TCP 连接建立起来后,就可以在两个方向传送数据流。当 TCP 的应用进程再没有数据需要发送时,就发关闭命令。 TCP 通过发送控制位 FIN=1 的数据片来关闭本方数据流,但还可以继续接收数据,直到对方关闭那个方向的数据流,连接就关闭。
TCP 协议使用修改的三次握手协议来关闭连接, 如图 3-11 所示,即终止一个连接要经过 4 次握手。这是因为 TCP 的半关闭( half-close )造成的。由于一个 TCP 连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭。关闭的原则就是当一方完成它的数据发送任务后就能发送一个 FIN 来终止这个方向连接。当一端收到一个 FIN ,它必须通知应用层另一端已经终止了那个方向的数据传送。发送 FIN 通常是应用层进行关闭的结果。
从一方的 TCP 来说,连接的关闭有三种情况:
• 本方启动关闭
收到本方应用进程的关闭命令后, TCP 在发送完尚未处理的报文段后,发 FIN = 1 的报文段给对方,且 TCP 不再受理本方应用进程的数据发送。在 FIN 以前发送的数据字节,包括 FIN ,都需要对方确认,否则要重传。注意 FIN 也占一个顺序号。一旦收到对方对 FIN 的确认以及对方的 FIN 报文段,本方 TCP 就对该 FIN 进行确认,在等待一段时间,然后关闭连接。等待是为了防止本方的确认报文丢失,避免对方的重传报文干扰新的连接。
• 对方启动关闭
当 TCP 收到对方发来的 FIN 报文时,发 ACK 确认此 FIN 报文,并通知应用进程连接正在关闭。应用进程将以关闭命令响 应。 TCP 在发送完尚未处理的报文段后,发一个 FIN 报文给对方 TCP ,然后等待对方对 FIN 的确认,收到确认后关闭连接。若对方的确认未及时到达,在等待一段时间后也关闭连接。
• 双方同时启动关闭
连接双方的应用进程同时发关闭命令,则双方 TCP 在发送完尚未处理的报文段后,发送 FIN 报文。各方 TCP 在 FIN 前所发报文都得到确认后,发 ACK 确认它收到的 FIN 。各方在收到对方对 FIN 的确认后,同样等待一段时间再关闭连接。这称之为同时关闭( simultaneous close )。
3.4.3 TCP 状态机
TCP 协议的操作可以使用一个具有 11 种状态的有限状态机( Finite State Machine )来表示,图 3-12 描述了 TCP 的有限状态机,图中的圆角矩形表示状态,箭头表示状态之间的转换,各状态的描述如表 3-2 所示。图中用粗线表示客户端主动和被动的服务器端建立连接的正常过程:客户端的状态变迁用粗实线,服务器端的状态变迁用粗虚线。细线用于不常见的序列,如复位、同时打开、同时关闭等。图中的每条状态变换线上均标有“事件/动作”:事件是指用户执行了系统调用( CONNECT 、 LISTEN 、 SEND 或 CLOSE )、收到一个报文段( SYN 、 FIN 、 ACK 或 RST )、或者是出现了超过两倍最大的分组生命期的情况;动作是指发送一个报文段( SYN 、 FIN 或 ACK )或什么也没有(用“-”表示)。
图 3-12 TCP 有限状态机。粗实线表示客户的正常路径;
粗虚线表示服务器的正常路径;细线表示不常见的事件。
每个连接均开始于 CLOSED 状态。当一方执行了被动的连接原语( LISTEN )或主动的连接原语( CONNECT )时,它便会脱离 CLOSED 状态。如果此时另一方执行了相对应的连接原语,连接便建立了,并且状态变为 ESTABLISHED 。任何一方均可以首先请求释放连接,当连接被释放后,状态又回到了 CLOSED 。
表 3-2 TCP 状态表
状 态 |
描 述 |
CLOSED |
关闭状态,没有连接活动或正在进行 |
LISTEN |
监听状态,服务器正在等待连接进入 |
SYN RCVD |
收到一个连接请求,尚未确认 |
SYN SENT |
已经发出连接请求,等待确认 |
ESTABLISHED |
连接建立,正常数据传输状态 |
FIN WAIT 1 |
(主动关闭)已经发送关闭请求,等待确认 |
FIN WAIT 2 |
(主动关闭)收到对方关闭确认,等待对方关闭请求 |
TIMED WAIT |
完成双向关闭,等待所有分组死掉 |
CLOSING |
双方同时尝试关闭,等待对方确认 |
CLOSE WAIT |
(被动关闭)收到对方关闭请求,已经确认 |
LAST ACK |
(被动关闭)等待最后一个关闭确认,并等待所有分组死掉 |
1. 正常状态转换
我们用图 3-13 来显示在正常的 TCP 连接的建立与终止过程中,客户与服务器所经历的不同状态。读者可以对照图 3-12 来阅读,使用图 3-12 的状态图来跟踪图 3-13 的状态变化过程,以便明白每个状态的变化:
在此状态下,双方可以自由传输数据。当一个应用程序完成数据传输任务后,它需要关闭 TCP 连接。假设仍由客户端发起主动关闭连接。
2. 同时打开:
尽管发生的可能性极小,两个应用程序同时彼此执行主动打开的情况还是可能的。每一方必须发送一个 SYN ,且这些 SYN 必须传递给对方。这需要每一方使用一个对方周知的端口作为本地端口。例如,主机 A 中的一个应用程序使用本地端口 7777 ,并与主机 B 的端口 8888 执行主动打开。主机 B 中的应用程序则使用本地端口 8888 ,并与主机 A 的端口 7777 执行主动打开。 TCP 是特意设计为了可以处理同时打开,对于同时打开它仅建立一条连接而不是两条连接(其他的协议族,最突出的是 OSI 传输层,在这种情况下将建立两条连接而不是一条连接)。
当出现同时打开的情况时,状态变迁与图 3-13 所示的不同。两端几乎在同时发送 SYN ,并进入 SYN_SENT 状态。当每一端收到 SYN 时,状态变为 SYN_RCVD ,同时它们都再发 SYN 并对收到的 SYN 进行确认。当双方都收到 SYN 及相应的 ACK 时,状态都变迁为 ESTABLISHED 。图 3-14 显示了这些状态变迁过程。
图 3-14 同时打开期间报文段的交换
一个同时打开的连接需要交换 4 个报文段,比正常的三次握手多一个。此外,要注意的是我们没有将任何一端称为客户或服务器,因为每一端既是客户又是服务器。
3. 同时关闭:
正常情况下都是由一方(通常但不总是客户方)发送第一个 FIN 执行主动关闭,但双方都执行主动关闭也是可能的, TCP 协议也允许这样的同时关闭。
在图 3-12 中,当两端应用层同时发出关闭命令时,两端均从 ESTABLISHED 变为 FIN_WAIT_1 。这将导致双方各发送一个 FIN ,两个 FIN 经过网络传送后分别到达另一端。收到 FIN 后,状态由 FIN_WAIT_1 变迁到 CLOSING ,并发送最后的 ACK 。当收到最后的 ACK 时,状态变化为 TIME_WAIT 。图 3-15 总结了这些状态的变化,从图中可以看出同时关闭与正常关闭使用的报文段交换数目相同。
图 3-15 同时关闭期间的报文段交换
4. 其它情况:
另外, TIME_WAIT 状态的等待超时需要再详细解释一下,因为它直接影响到网络应用程序的表现。
每个具体 TCP 实现必须选择一个报文段最大生存时间 MSL ( Maximum Segment Lifetime ),它是任何报文段被丢弃前在网络内的最长时间。我们知道这个时间是有限的,因为 TCP 报文段以 IP 数据报在网络内传输,而 IP 数据报有限制其生存时间的 TTL 字段。 RFC 793 [Postel 1981c ] 指出 MSL 为 2 分钟。然而,实现中的常用值是 30 秒、 1 分钟、或 2 分钟。
对一个具体实现所给定的 MSL 值,处理的原则是:当 TCP 执行一个主动关闭,并发回最后一个 ACK ,该连接必须在 TIME_WAIT 状态停留的时间为 2 倍的 MSL ,因此 TIME_WAIT 状态也称为 2MSL 等待状态。在这段时间内,如果最后的 ACK 丢失,对方会超时并重发最后的 FIN ,这样本地 TCP 可以再次发送 ACK 报文段(这也是它唯一可以发送的报文,并重置 2MSL 定时器)。
这种 2MSL 等待的另一个结果是这个 TCP 连接在 2MSL 等待期间,定义这个连接的套接字( socket ,客户的 IP 地址和端口号,服务器的 IP 地址和端口号)不能再被使用。这个连接只能在 2MSL 结束后才能再被使用。在连接处于 2MSL 等待时,任何迟到的报文段将被丢弃。
我们假设图 3-12 中是客户执行主动关闭并进入 TIME_WAIT ,这是正常的情况,因为服务器通常执行被动关闭,不会进入 TIME_WAIT 状态。这暗示如果我们终止一个客户程序,并立即重新启动这个客户程序,则这个新客户程序将不能重用相同的本地端口。这不会带来什么问题,因为客户使用本地端口,而并不关心这个端口号是什么。然而,对于服务器,情况就有所不同,因为服务器使用周知端口。如果我们终止一个已经建立连接的服务器程序,并试图立即重新启动这个服务器程序,服务器程序将不能把它的这个周知端口赋值给它的端点,因为那个端口是处于 2MSL 连接的一部分。在重新启动服务器程序前,它需要在 1~4 分钟。这就是很多网络服务器程序被杀死后不能够马上重新启动的原因(错误提示为“ Address already in use ”)。
和 IP 一样, TCP 也是 TCP/IP 协议簇中最为重要的协议。本章详细地介绍了 TCP 的工作原理、数据报格式,特别是 TCP 连接建立与关闭的状态转换。由于 TCP 是离应用层最近的底层协议,因此 TCP 的很多状态在上层应用中是可见的,在后面的章节中,很多地方都涉及到 TCP 的各种状态。因此,掌握本章介绍的原理和概念,对于学好后面的章节极为有利,特别是掌握了 TCP 的状态转换规律,对于网络的配置与诊断、以及网络应用的调试大有裨益。