26.3 Rlogin的例子
在这里举两个例子:第一个是当R l o g i n会话建立的时候,客户和服务器的协议交互;从第
二个例子可以看到,当用户键入中断键以取消正在服务器运行的程序时,服务器将产生很多
输出。在图1 9 - 2中,我们给出了通常情况下,R l o g i n会话上的数据流交互情况。
26.3.1 初始的客户-服务器协议
图2 6 - 5显示的是从主机b s d i到服务器s v r 4的R l o g i n建立一个连接时的时间系列(在图中,去
掉了通常的T C P连接的建立过程,窗口通告以及服务类型信息)。
上节介绍的协议对应图中的报文段 1 ~ 9。客户发送一个字节的0 (报文段1)之后发送3个
字符串(报文段 3 )。在本例中,这3个字符串分别是: r s t e v e n s (客户的登录名)、r s t e v e n s
(服务器的登录名)和i b m p c 3 / 9 6 0 0 (终端类型和速率)。当服务器确认了这些信息后回送一个
字节的0 (报文段5)。
然后服务器发送窗口请求命令(报文段7 )。这是采用T C P紧急方式发送的,我们又一次看
到一个实现( S V R 4 )采用较老的但更普通的解释,即紧急指针指明的序号是紧急数据的最后一
个字节加1。客户回送1 2字节的数据:2字节的0 x ff,2字节的‘s ’,4个16 bit长度的窗口数据。
下面的4个报文段( 10, 12, 14和1 6)是由服务器发送的,是从服务器操作系统的问候
( g r e e t i n g ) 。之后报文段1 8是一个7字节长度的外壳进程提示符“s v r 4 %”。
客户输入的信息如图 1 9 - 2所示,每次发送一个字节。客户和服务器都可以主动中断该连
接。如果我们输入一个命令,让服务器的外壳程序终止运行,那么服务器将中断该连接。如
果我们给R l o g i n客户键入一个转移符(通常是一个“ ~ ”),紧跟着一个句点或者是一个文件结
束符号,那么客户将主动关闭该连接。
----------------------- Page 7-----------------------
图2 6 - 5 中,客户进程的端口号是 1 0 2 3,这是由I A N A分配的(在 1 . 9节中介绍)。
R l o g i n协议要求客户进程用小于1 0 2 4的端口号,术语叫做保留端口。在U n i x系统中,客
户进程一般不能使用保留端口号,除非客户进程具有超级用户权限。这是客户进程和服
务器进程相互鉴别的一部分,这种鉴别可以使得用户不需要口令而可以登录。[ S t e v e n s
1 9 9 0 ]详细讨论了客户进程和服务器进程相互鉴别的过程和有关保留端口号的问题。
图26-5 Rlogin连接时间次序
26.3.2 客户中断键
让我们看一下另外一个例子,这个例子涉及到 T C P 的紧急方式。当数据流已经终止时,
我们键入中断键。这个例子要用到前面讲到的很多 T C P算法如:紧急方式、糊涂窗口避免技
术、窗口流量控制和坚持计时器。在主机 s u n上运行客户进程。我们登录到主机 b s d i,向终
端输出一个大文本文件,然后键入 C o n t r o l _ S 中断输出。当输出停止时,我们键入中断键
(D E L E T E )以异常方式中止该进程。
----------------------- Page 8-----------------------
sun % rlogin bsdi
所有操作系统的问候
bsdi % cat /usr/share/misc/termcap 向终端输出大文件
大量的终端输出
键入C o n t r o l _ S以中断输出,
然后等待直到输出停止
^? 键入中断键,而这被回显了,
bsdi % 然后输出了提示符
下面这些要点是关于客户、服务器和连接的状态的概述:
1) 键入C o n t r o l _ S 以停止终端的输出。
2) 用户终端的输出缓存很快被填满,所以R l o g i n 的客户向终端的写操作被阻塞。
3) 此时客户也不能从网络连接上读取数据,所以客户的 T C P接收缓存也将被填满。
4) 当接收缓存已满时,客户进程的T C P会向服务器进程的T C P通告现在的接收窗口是0 。
5) 当服务器收到客户的窗口为0时,将停止向客户发送数据,这样,服务器的发送缓存也
将被填满。
6) 由于发送缓存已满,所以R l o g i n服务器进程将停止。这样,R l o g i n服务器将不能从服务
器运行的应用程序(c a t)处读取数据。
7) 当c a t程序的输出缓存也被填满时,c a t也将停止。
8) 然后我们用中断键来终止服务器上的 c a t程序。这个命令从客户的 T C P传输到服务器
的T C P ,这是因为该方向的数据传输没有被流量控制所终止。
9) c a t应用程序收到中断命令并且终止。这使得它的输出缓存(也就是 R l o g i n服务器进程
读取数据的地方)被清空,这将唤醒R l o g i n服务器进程。然后R l o g i n服务器进程进入紧急方式,
向客户进程发送“清仓输出”命令(0 x 0 2 )。
图2 6 - 6概括了从服务器到客户的数据流(图中的序号就是下面将介绍的图中的时间系列)。
图26-6 Rlogin例子中,服务器进程到客户进程的数据流概述
发送缓存的阴影部分是4 0 9 6字节的缓存中没有被使用的部分。图2 6 - 7是该例子的时间系列。
在报文段1 ~ 3,服务器进程向客户进程发送满长度(即 1 0 2 4字节)的T C P报文段。由于此
时客户进程不能向终端写信息,客户进程也不能从网络上读数据,所以在报文段 4 中,客户进
程向服务器进程发送A C K确认时,告诉服务器进程此时接收窗口是1 0 2 4个字节。在报文段5中,
服务器进程发送的数据长度就不再是满长度的了。同样,报文段 6 中客户进程的确认信号所带
的接收窗口大小是此时接收缓存的空余字节长度。那么在报文段 5中,客户进程A C K信号中为
什么接收窗口大小是3 4 9而不是0呢?这是因为如果发送的是0 (糊涂窗口避免技术),那么窗
口指针将右边界移动到了左边界,而这是绝对不能发生的(见 2 0 . 3节)。当服务器进程收到报
----------------------- Page 9-----------------------
文段6的A C K信号后,它就不能再发送全长的数据报了,这时候它就采用糊涂窗口症避免技术,
不发送任何东西,同时置一个 5秒的坚持计时器。当计时器超时,服务器进程就发送一个 3 4 9
字节大小的数据(如报文段 7 )。由于此时客户进程依然不能输出接收缓存的信息,所以接收
缓存将被填满,客户进程将发送A C K信号,此时接收窗口大小为0 (如报文段8)。
这时候我们键入中断键并且以报文段 9显示的那样传输。此时的接收窗口大小依然为 0 。
当服务器进程接收到该中断键后,服务器进程把它发送给应用程序( c a t ),应用程序就终止。
由于应用程序被终端中断键所终止,应用程序就清空它的输出缓存。服务器进程发现该变化
后就通过T C P紧急方式向客户进程发送“清仓输出”命令,这如报文段 1 0所示。注意命令字
节0 x 0 2放在第3 0 1 4 6字节中(紧急指针减1)。报文段1 0告诉客户进程在命令字节前还有3 4 1 9个
字节(从2 6 7 2 7到3 0 1 4 5 )在服务器进程的发送缓存中等待发送。
报文段1 0采用紧急通知方式发送,包含了服务器进程向客户进程发送的下一个字节(序
号是2 6 7 2 7 )。它不包含“清仓输出”命令字节。记得在 2 2 . 2节中曾经介绍过,发送进程可以
发送一个字节的数据来试探对方的接收窗口是否关闭。报文段 1 0就是采用了这个原理。然后
客户进程T C P就立即发送如报文段 11所示的数据。虽然此时接收窗口还是 0,但是在客户进程
内部,由于客户进程的T C P收到了对方的紧急通知,它把该通知告诉客户进程,客户进程就
知道服务器进程已经进入了紧急方式了。
图26-7 Rlogin举例:当客户程停止输出然后终止服务器的应用程序的情况
----------------------- Page 10-----------------------
当R l o g i n客户进程从它的T C P收到了紧急通知,并且客户进程开始读取已经在输入缓存中
等待被读取的数据时,接收窗口就会重新打开(报文段 1 3)。然后服务器进程就开始正常发送
数据(报文段14, 15, 17和1 8)。注意报文段1 8的数据报中包含紧急数据的最后一个字节的数据
(序号3 0 1 4 6 ),该字节包含服务器进程发送给客户进程的命令字节。当客户进程收到该命令后,
它就丢弃报文段 1 4、1 5、1 7和1 8所收到的数据,并且清空终端的输出缓存。在报文段 1 9中的
下两个字节是中断键的回显“^ ? ”。最后一个报文段(2 1 )包含了客户进程的外壳提示符。
这个例子描述了当用户键入中断键后,连接的双方数据如何被存储的情况。如果这些动
作仅仅丢弃在服务器的 3 4 1 9个字节数据,而不丢弃已经在客户的 4 0 9 6个字节的数据,那么这
些已经在客户的终端输出缓存中的4 0 9 6字节数据将输出到终端上。
26.4 Telnet协议
Te l n e t协议可以工作在任何主机(例如,任何操作系统)或任何终端之间。 RFC 854
[Postel 和Reynolds 1983a]定义了该协议的规范,其中还定义了一种通用字符终端叫做网络虚
拟终端N V T (Network Virtual Te r m i n a l)。N V T是虚拟设备,连接的双方,即客户机和服务器,
都必须把它们的物理终端和 N V T进行相互转换。也就是说,不管客户进程终端是什么类型,
操作系统必须把它转换为N V T格式。同时,不管服务器进程的终端是什么类型,操作系统必
须能够把N V T格式转换为终端所能够支持的格式。
N V T是带有键盘和打印机的字符设备。用户击键产生的数据被发送到服务器进程,服务
器进程回送的响应则输出到打印机上。默认情况下,用户击键产生的数据是发送到打印机上
的,但是我们可以看到这个选项是可以改变的。
26.4.1 NVT ASCII
术语NVT ASCII代表7 比特的A S C I I字符集,网间网协议族都使用NVT ASCII 。每个7 比特
的字符都以8比特格式发送,最高位比特为0 。
行结束符以两个字符 C R (回车)和紧接着的L F (换行)这样的序列表示。以\ r \ n来表
示。单独的一个 C R也是以两个字符序列来表示,它们是 C R和紧接着的N U L (字节0 ),以
\ r \ 0表示。
在下面的章节中可以看到,F T P, SMTP, Finger和W h o i s协议都以NVT ASCII来描述客户命
令和服务器的响应。
26.4.2 Telnet命令
Te l n e t通信的两个方向都采用带内信令方式。字节 0 x f f (十进制的2 5 5 )叫做I A C
(interpret as command ,意思是“作为命令来解释”)。该字节后面的一个字节才是命令字节。
如果要发送数据2 5 5 ,就必须发送两个连续的字节2 5 5 (在前面一节中我们讲到数据流是N V T
A S C I I ,它们都是7 b i t 的格式,这就暗示着 2 5 5这个数据字节不能在 Te l n e t上传输。其实在
Te l n e t 中有一个二进制选项,在R F C 8 5 6 [ P o s t e l和Reynolds 1983b] 中有定义,关于这点我们没
有讨论,该选项允许数据以8 b i t进行传输)。图2 6 - 8列出了所有的Te l n e t命令。
由于这些命令中很多命令很少用到,所以对于一些重要的命令,如果在下面章节的例子
或叙述中遇到,我们再做解释。
----------------------- Page 11-----------------------
图26-8 当前一个字节是IAC (255)时的Telnet命令集
26.4.3 选项协商
虽然我们可以认为Te l n e t连接的双方都是N V T,但是实际上Te l n e t连接双方首先进行交互
的信息是选项协商数据。选项协商是对称的,也就是说任何一方都可以主动发送选项协商请
求给对方。
对于任何给定的选项,连接的任何
一方都可以发送下面 4种请求的任意一 个请求。
1) WILL :发 送 方 本 身 将 激 活 ( e n a b l e )选项。
2) DO :发送方想叫接收端激活选 项。
3) WONT :发送方本身想禁止选项。
4) DON’T :发送方想让接收端去禁止选项
由于Te l n e t规则规定,对于激活选项请求(如1和2 ),有权同意或者不同意。而对于使选项失效请求(如 3和4 ),必须同意。这
样,4种请求就会组合出6种情况,如图2 6 - 9所示。
图26-9 Telnet选项协商的6种情况
选项协商需要3个字节:一个I A C字节,接着一个字节是WILL, DO, WONT和D O N T这四
----------------------- Page 12-----------------------
者之一,最后一个I D字节指明激活或禁止选项。
现在,有4 0 多个选项是可以协商的。A s s i g n e d Number RFC 文档中指明选项字节的值,并且
一些相关的R F C文档描述了这些选项。图 2 6 -1 0显示了在本章中会出现的选项代码。
Te l n e t的选项协商机制和Te l n e t协议的大部分内容一样,是对称的。连接的双方都可以发
起选项协商请求。但我们知道,远程登录不是对称的应用。客户进程完成某些任务,而服务 某些Te l n e t选项仅仅
适合于客户进程(例如要求激活行模式方式),某些选项则仅仅适合于 服务器进程。
图26-10 本章中将讨论的Telnet选项代码
26.4.4 子选项协商
有些选项不是仅仅用“激活”或“禁止”就能够表达的。指定终端类型就是一个例子,
客户进程必须发送用一个A S C I I字符串来表示终端类型。为了处理这种选项,我们必须定义子
选项协商机制。
在R F C 1 0 9 1 [ VanBokkelen 1989] 中定义了如何表示终端类型这样的子选项协商机制。首先
连接的某一方(通常是客户进程)发送3个字节的字符序列来请求激活该选项。
<IAC, WILL, 24>
这里的2 4 (十进制)是终端类型选项的I D号。如果收端(通常是服务器进程)同意,那
么响应数据是:
<IAC, DO, 24>
然后服务器进程再发送如下的字符串:
<IAC, SB, 24, 1, IAC, SE>
该字符串询问客户进程的终端类型。其中 S B是子选项协商的起始命令标志。下一个字节
的“2 4 ”代表这是终端类型选项的子选项(通常S B后面的选项值就是子选项所要提交的内容)。
下一个字节的“ 1”表示“发送你的终端类型”。子选项协商的结束命令标志也是 I A C ,就像
S B是起始命令标志一样。如果终端类型是i b m p c,客户进程的响应命令将是:
<IAC, SB, 24, 0‘I’, ‘B’, ‘M’, ‘P’, ‘C’, IAC, SE>
第4个字节“0”代表“我的终端类型是”(在Assigned Numbers RFC文档中有正式的关于
终端类型的数值定义,但是最起码在 U n i x系统之间,终端类型可以用任何对方可理解的数据
进行表示。只要这些数据在t e r m c a p或t e r m i n f o数据库中有定义)。在Te l n e t子选项协商过程中,
终端类型用大写表示,当服务器收到该字符串后会自动转换为小写字符。