第18章 TCP连接的建立与终止
18.7 复位报文段
我们已经介绍了T C P首部中的R S T比特是用于“复位”的。一般说来,无论何时一个报文段发往基准的连接( referenced connection)出现错误,T C P都会发出一个复位报文段(这里提到的“基准的连接”是指由目的 I P地址和目的端口号以及源 I P地址和源端口号指明的连接。这就是为什么RFC 793称之为插口)。
18.7.1 到不存在的端口的连接请求
产生复位的一种常见情况是当连接请求到达时,目的端口没有进程正在听。对于 U D P,我们在6 . 5节看到这种情况,当一个数据报到达目的端口时,该端口没在使用,它将产生一个I C M P端口不可达的信息。而T C P则使用复位。
产生这个例子也很容易,我们可使用 Te l n e t客户程序来指明一个目的端口没在使用的情况:
代码语言:javascript复制bsdi % telnet svr4 20000 端口2 0 0 0 0未使用
Trying 140.252.13.34...
telnet: Unable to connect to remote host: Connection refused
Te l n e t客户程序会立即显示这个差错信息。图 1 8 - 1 4显示了对应这个命令的分组交换过程。
在这个图中需要注意的值是复位报文段中的序号字段和确认序号字段。因为 A C K比特在到达的报文段中没有被设置为 1,复位报文段中的序号被置为 0,确认序号被置为进入的 I S N加上数据字节数。尽管在到达的报文段中没有真正的数据,但 S Y N比特从逻辑上占用了 1字节的序号空间;因此,在这个例子中复位报文段中确认序号被置为 I S N与数据长度(0)、S Y N比特所占的1的总和。
18.7.2 异常终止一个连接
我们在 1 8 . 2节中看到终止一个连接的正常方式是一方发送 F I N。有时这也称为有序释放(orderly release),因为在所有排队数据都已发送之后才发送 F I N,正常情况下没有任何数据丢失。但也有可能发送一个复位报文段而不是 F I N来中途释放一个连接。有时称这为异常释放(abortive release)。
异常终止一个连接对应用程序来说有两个优点: (1)丢弃任何待发数据并立即发送复位报文段; (2)R S T的接收方会区分另一端执行的是异常关闭还是正常关闭。应用程序使用的A P I必须提供产生异常关闭而不是正常关闭的手段。
使用s o c k程序能够观察这种异常关闭的过程。 Socket API通过“linger on close”选项(S O _ L I N G E R)提供了这种异常关闭的能力。我们加上 - L选项并将停留时间设为 0。这将导致连接关闭时进行复位而不是正常的 F I N。我们连接到处于服务器上的 s o c k程序,并键入一输入行:
图1 8 - 1 5是这个例子的t c p d u m p输出显示(在这个图中我们已经删除了所有窗口大小的说明,因为它们与讨论无关)。 第1 ~ 3行显示出建立连接的正常过程。第 4行发送我们键入的数据行( 1 2个字符和U n i x换行符),第5行是对收到数据的确认。
第6行对应为终止客户程序而键入的文件结束符(C o n t r o l _ D)。由于我们指明使用异常关闭而不是正常关闭(命令行中的- L 0选项),因此主机b s d i端的T C P发送一个R S T而不是通常的F I N。R S T报文段中包含一个序号和确认序号。需要注意的是 R S T报文段不会导致另一端产生任何响应,另一端根本不进行确认。收到R S T的一方将终止该连接,并通知应用层连接复位。 我们在服务器上得到下面的差错信息:
这个服务器程序从网络中接收数据并将它接收的数据显示到其标准输出上。通常,从它的T C P上收到文件结束符后便将结束,但这里我们看到当收到 R S T时,它产生了一个差错。这个差错正是我们所期待的:连接被对方复位了。
18.7.3 检测半打开连接
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的 T C P连接称为半打开(H a l f - O p e n)的。任何一端的主机异常都可能导致发生这种情况。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。
半打开连接的另一个常见原因是当客户主机突然掉电而不是正常的结束客户应用程序后再关机。这可能发生在使用 P C机作为Te l n e t的客户主机上,例如,用户在一天工作结束时关闭P C机的电源。当关闭P C机电源时,如果已不再有要向服务器发送的数据,服务器将永远不知道客户程序已经消失了。当用户在第二天到来时,打开 P C机,并启动新的Te l n e t客户程序,在服务器主机上会启动一个新的服务器程序。这样会导致服务器主机中产生许多半打开的T C P连接(在第2 3章中我们将看到使用T C P的k e e p a l i v e选项能使T C P的一端发现另一端已经消失)。
能很容易地建立半打开连接。在 b s d i上运行Te l n e t客户程序,通过它和s v r 4上的丢弃服务器建立连接。我们键入一行字符,然后通过 t c p d u m p进行观察,接着断开服务器主机与以太网的电缆,并重启服务器主机。这可以模拟服务器主机出现异常(在重启服务器之前断开以太网电缆是为了防止它向打开的连接发送 F I N,某些T C P在关机时会这么做)。服务器主机重启后,我们重新接上电缆,并从客户向服务器发送另一行字符。由于服务器的 T C P已经重新启动,它将丢失复位前连接的所有信息,因此它不知道数据报文段中提到的连接。 T C P的处理原则是接收方以复位作为应答。
图1 8 - 1 6是这个例子的t c p d u m p输出显示(已从这个输出中删除了窗口大小的说明、服务类型信息和M S S声明,因为它们与讨论无关)。
第1 ~ 3行是正常的连接建立过程。第 4行向丢弃服务器发送字符行“ h i t h e r e”,第5行是确认。
然后是断开s v r 4的以太网电缆,重新启动s v r 4,并重新接上电缆。这个过程几乎需要 1 9 0秒。接着从客户端输入下一行(即“ another line”),当我们键入回车键后,这一行被发往服务器(图1 8 - 1 6的第6行)。这导致服务器产生一个响应,但要注意的是由于服务器主机经过重新启动,它的 A R P高速缓存为空,因此需要一个 A R P请求和应答(第 7、8行)。第9行表示R S T被发送出去。客户收到复位报文段后显示连接已被另一端的主机终止( Te l n e t客户程序发出的最后信息不再有什么价值)。