分类: 系统运维
2008-07-30 17:13:10
文件只通过数据连接传输。控制连接用来发送操作命令以及相应的命令响应(参见FTP响应一章)。一些命令与主机间数据传输有关。这些数据传输命令包 括:指定数据位怎样被传输的模式(MODE)命令,以及用来定义数据表示方式的结构(STRU)类型(TYPE)命令。传送和表示基本上是独立的,但“流 式”传输模式依赖于文件结构参数,而当使用“压缩”传送模式时,填充字节的表示依赖于表示类型。
数据由发送端主机存储设备传输到接收端主机的存储设备上。由于两个系统的数据存储形式不同,经常需要将数据转换形式。例如,NVT-ASCII在不
同的系统中有不同的存储表示。DEC TOP-20一般用5个7位的ASCII字符存储NVT-ASCII,左对齐成36位的字。IBM
Mainframe用8位EBCDIC编码存储NVT-ASCII。Multics将NVT-ASCII存储成4个9位字符组成的字。当在不同的系统中传
输字符时理应将其转换成标准的NVT-ASCII表示。发送和接收端则应相应地在标准表示法和内部表示法间转换。
当传输二进制数据时表示法的另一个问题就是不同主机有不同的字长度。并不总是明确发送端怎样发送数据以及接收端怎样接收数据。例如,当从一个32位字长的
系统传输32位字节到一个36位字长的系统时,应该(为了高效和实用)在后一个系统中将32位字节在36位字中右对齐。无论哪种情况,用户都应该可以选择
数据表示形式和传输功能。应该注意FTP提供了非常有限的数据表示形式。传输这些表示形式之外的数据时用户应该自行转换。
当用户指定一个表示类型时,FTP为我们管理数据表示。这种类型可能隐含的(ASCII/EBCDIC)或显式的(本地字节)为解释器作为“逻辑字节长度
”定义字节长度。注意这并不是用于在数据连接传输时的字节长度,被称为“传输字节长度”,两种长度不能互相冲突。例如,NVT-ASCII具有8位的逻辑
字节长度。如果类型是本地字节,那么TYPE命令必须有第二个参数指定逻辑字节长度。传输字节长度始终是8位。
这是缺省类型,必须被所有FTP实现支持。主要用来传输文本文件,除非主机双方认为EBCDIC类型更方便。
发送方将内部字符表示转换为标准的8位NVT-ASCII表示(参见Telnet协议)。接收方将标准格式数据转换为它自己的内部格式。
NVT规定,
用标准NVT-ASCII表示意味着数据必须解释为8位字节。
用于ASCII和EBCDIC格式参数将在下面讨论。
这种类型用来在使用EBCDIC编码的主机间高效地传输。
传输时,数制被表示为8位的EBCDIC字符。EBCDIC与ASCII类型的区别仅仅是字符编码的不同。
行尾(End-of-Line)很少用在EBCDIC类型中表示结构,必要时应该用
数据以8位连续字节流传输。接收端必须将数据存储为连续位。存储系统结构可能要将文件(或对于记录结构文件来说,每个记录)填充到合适的边界(字节、字或
块)。填充的字节必须为0,并追加到文件末尾(或每个记录末尾)。必须有方法来指出填充字节,当取得文件时,以将填充字节剔除。填充转换方法应当公开,使
用户可以方便的处理文件。
图像类型目的是为了高效地存储和检索文件,以及传输二进制文件。建议所有的FTP实现都应该支持这个类型。
数据以参数Byte size指定的逻辑字节长度传输。字节长度值必须是十进制整数,并且没有缺省值。逻辑字节长度不一定要和传输字节长度一样。如果字节长度不同,那么逻辑字节将忽略传输字节边界连续打包,并在最后做必要的填充。
当数据到达接收端主机时,将以独立的方式被转换为特定主机的逻辑字节长度。这个转换过程必须是可逆的(就是说,用同样的参数会产生同样的文件)并且应该被FTP实现者公开。
例如,用户发送36位浮点数到一个32位字长的主机时可以以本地字节长度36来发送。接收端主机将存储逻辑字节,以方便操作。在这个例子中,将36位的逻辑字节放入64位双字中将满足需要。
另一个例子中,一对用36位字长的主机间用“TYPE L 36”传送数据。数据将用8位传输字节包装,因此9个传输字节代表两个主机字。
ASCII和EBCDIC类型也支持第二个可选的参数。这代表了一种纵向的文件格式控制。以下数据表示类型在FTP中定义:
一个被传输到主机的字符文件可能具有以下三个目的之一:为了打印;为了存储用来以后重现;为了处理。如果文件传送是为了打印,接收主机必须知道垂直控制是
如何被表示的。第二种目的中,可能需要在主机中存储为一个文件,日后将其重现为一样的格式。最后一种目的中,必须保证将文件从一主机传输到另一主机并在第
二台主机上处理文件并不带来麻烦。单独的ASCII或EBCDIC格式不能满足所有这些条件。因此,这些类型具有第二个参数指定以下三种格式之一:
如果第二个格式参数被省略,这将是缺省格式。非打印格式必须被所有FTP实现支持。
文件不要包含垂直格式信息。如果文件被送到打印过程,那么打印过程将假定使用标准的间距和页边距值。
一般来说,这个格式被用作处理或存储。
文件包含ASCII/EBCDIC垂直格式控制(也就是,
文件包含ASA(FORTRAN)垂直格式控制字符。(参见RFC 740附录C;《Communications of the
ACM》7卷,10章,606页,1964十月)ASA标准规定,每行或记录的头一个字符不用来打印。这个字符用来决定本行或记录打印机的垂直走纸量。
ASA标准指定如下控制字符:
字符 垂直间距
空 走纸一行
0 走纸两行
1 走纸到下页顶
+ 不移动,也就是覆盖打印
打印机过程必须有方法区分结构体的结束。如果文件具有记录结构(后面将介绍)就没有问题;记录会在传输与存储中显式的标记。如果文件没有记录结构,将以
由于表示类型的不同,FTP允许文件具有指定的结构。FTP中定义了以下三种文件结构:
文件结构,内部没有结构,文件被视为连续的数据字节流
记录结构,文件由连续的记录组成
页结构,文件由独立的具有索引的页组成
如果没有使用结构命令(STRU),文件结构是缺省值。但在所有的FTP实现中,文件和记录结构必须用在“文本”文件(就是说,带有TYPE ASCII或EBCDIC的文件)里。文件结构将影响文件的传输模式(参见传输模式一章)以及文件的表示和存储。
文件的“自然”结构取决于存储文件的的主机。源代码文件在IBM Mainframe上以固定长度的记录存储,而在DEC
TOPS-20以用类似于
在基于文件结构的主机和基于记录结构的主机间传输文件时可能会出现问题。如果文件是基于记录结构传输到基于文件结构的主机,应该在内部将记录结构转换为文件结构。显然这种转换应该能够可逆,以便可以再转回记录结构。
在将文件从基于文件结构的主机传输到基于记录结构的主机时,存在如何将文件切分成记录的问题。如果必须切分一个文本文件,那么FTP实现应该使用行末符,ASCII中是
如果没有使用结构命令(STRU),文件结构就默认使用。
在文件结构中没有内部结构,文件被当作连续的字节流。
在所有的FTP实现中,必须支持“文本”文件(就是,使用TYPE ASCII或EBCDIC)的记录结构。
在记录结构文件中,文件由连续的记录组成。
为了传输不连续的文件,FTP定义了页结构。一般说的“随机存取文件”或“多穴文件”属于这个类型。对于这些文件,一般有另外的对应整个文件信息(例如,文件描述符),或者对应文件部分信息(例如,页存取控制),或两者都有。在FTP中,文件的部分称为页。
为了提供不同页大小以及相关信息,每页传输时将额外包括一个页头。页头有如下定义的域:
头长度
包括这个字节在内的头逻辑长度。最小头长度是4。
页索引
文件区域的逻辑页号。并不是传输的序列号,而是标识本页的索引号。
数据长度
页中数据的逻辑字节数。最小数据长度为0。
页类型
标示了页的类型。定义了如下的类型:
0 = 最末页
用来标示页结构传输结束。页头长度必须为4,数据长度必须为0。
1 = 单独页
对于没有页相关控制信息的单独页来说这是普通的类型。页头长度必须为4。
2 = 描述页
这个类型用来传输整个文件的描述信息。
3 = 存取控制页
此类型包括一个额外的指定页存取信息的头域。头长度必须为5。
可选域
其他的头域可能用来提供每页的控制信息,例如,每页的存取控制。
所有域都是一个逻辑字节。逻辑字节长度由TYPE命令指定。参见附录I中的更详细信息以及一个页结构的例子。
关于参数需要注意的一点:必须用相同参数续传相同的文件。相应的,FTP实现在用相同参数续传文件时要保证传输的文件与原始文件相同。
传输数据的过程包括在指定端口建立数据连接选择传输参数。用户和服务器DTP都有缺省的端口号。用户过程缺省的数据端口与控制连接端口相同(也就是,端口U)。服务器过程的默认端口与控制连接的端口相邻(也就是L-1)。
传输字节长度是8位字节长。这个字节长度只与实际传输数据有关;而与主机文件系统的数据表示无关。
被动数据传输过程(可能是用户DTP或另一服务器DTP)应该在发送FTP请求命令之前“监听”在数据端口。FTP请求命令决定了数据传输方向。服务器在
接到传输请求后将建立到指定端口的连接。当连接建立后,数据将在两端DTP间传输,同时服务器PI向用户PI发送确认回复。
每个FTP实现必须支持使用缺省的数据端口,只有用户PI可以使用变化的非缺省端口。
用户可能会用PORT命令指定一个其他的数据端口。用户可能想将文件下载到TAC行式打印机或者从第三方主机下载。后种情况下,用户PI同时建立到两服务
器PI的控制连接。一个服务器(用FTP命令)等待连接,另一个服务器建立连接。用户PI给一个服务器PI发送PORT命令指示另一服务器的数据端口。最
后,向两端发送合适的传输命令。用户控制端与服务器间传送的详细命令以及回复顺序定义在FTP响应一章。
一般来说,维护数据连接是服务器的责任,包括连接的建立与关闭。例外的情况是当用户DTP在传输模式下发送数据时需要关闭连接表示文件结束。服务器必须在以下条件下关闭数据连接:
1. 服务器在传输模式下完成数据传输,需要关闭连接,表示文件结束。
2. 服务器收到用户发来的ABORT命令。
3. 用户用命令改变了端口设定。
4. 控制连接合法地或由于其他原因关闭。
5. 发生了不可挽回的错误。
其他情况下是否关闭连接是服务器可选择的,这种情况下服务器必须用250或226号响应通知用户过程。
缺省数据连接端口:所有FTP实现必须支持使用缺省数据连接端口,只有用户PI可能使用非缺省端口。
协商非缺省端口:用户PI可能使用PORT命令指定非缺省用户端口。用户PI可能要求服务器端用PASV命令指定非缺省端口。连接用一对地址指定,上面两种动作之一都会得到一个不同的连接,仍然允许同时使用两个命令在两端指定新的端口。
数据连接复用:当使用流模式传输数据时,在文件传输结束后必须关闭连接。如果有多个文件传输时可能带来的问题是TCP为了保证传输可靠要保持连接记录一段时间。因此不能马上重新连接。
有两种解决方案。第一种是协商一个非缺省端口。第二种是使用另一种传输模式。
对于传输模式,流式传输模式有天生的不可靠性,不能确定连接是否过早的关闭。其他的传输模式(块,压缩)不用关闭连接来指示文件结束。他们使用FTP编码来确定文件结束。因此使用这些模式可以在多文件传输时保持使用同一个数据连接。
传输数据时下一个要考虑的问题是选择合适的传输模式。有三种传输模式:一个对数据格式化,并允许重新开始过程;一个压缩数据提供高效传输;一个不加修改的传输数据。最后一种模式与结构属性配合决定处理过程。在压缩模式中,表示类型决定填充字节。
所有的数据传输必须显式的或隐式的用关闭数据连接来指示文件结束(EOF)。对记录结构的文件,所有的记录结束标志(EOR)都是显式的,包括最后一个记录。对于使用文件结构的传输,使用“末页”的页类型。
注意:在本章其他部分,除非明确指出,字节都表示“传输字节”。
为了使传输标准化,发送主机将根据传输模式和文件结构把行尾或记录尾转换成传输时的格式,接收主机将进行相反的转换。IBM
Mainframe的记录记数域可能不会被另一台主机识别,因此在流模式中记录尾信息可能以两字节的控制码来传输,在块模式或压缩模式中作为标志位。没有
记录结构的ASCII或EBCDIC文件中的行尾应该分别表示为
FTP定义了如下传输模式:
数据以字节流传输。对表示类型没有限制;可以使用记录结构。
在记录结构文件中,EOR和EOF将分别用两个字节的控制码表示。第一个字节都是同样的escape字符。第二个字节中,EOR将低位置一,其他位置
零;EOF则是将第二低位置一;也就是这个字节对于EOR来说是1,对于EOF来说是2。EOR和EOF可能在传输结束时通过使最低两置一来同时指定(就
是值3)。如果想发送escape字符,要在第二个字节再重复一次。
如果结构是文件结构,则使用关闭主机连接来指示EOF,传输的所有数据字节就是原始字节。
文件以连续的带有数据头的数据块来传输。数据头包括一个计数域和描述码。计数域指示了数据块整个长度,由此可以算出下一数据块的开始位置(没有填充位)。
描述码定义了:文件最后一块(EOF),记录最后块(EOR),重开始标记(参见错误恢复和重开始章)或者怀疑数据(也就是被怀疑在传输中可能不可靠的数
据)。最后的描述符不是FTP错误控制的一部分。它用来在站点间交换指定类型的数据(比如地震或天气数据)而且简略本地错误(比如磁带读错误)。记录结构
可以在这种模式下使用,而且可以用任何表示类型。
头包括3个字节。在这24位的头信息中,低16位表示字节记数,高8位表示描述符。
块头
+----------------+----------------+----------------+
| 描述符 | 字节记数 |
| 8 bits | 16 bits |
+----------------+----------------+----------------+
描述符字节由各个标志位组成。指定了4个描述码,每一个描述码为描述符的十进制值。
描述码 意义
128 数据块结束是EOR
64 数据块结束是EOF
32 怀疑数据块有错
16 数据块是重开始标志
通过对不同的标志位置一,每个数据块可以使用不同的描述符组合。
重开始标志是在数据流中的8位整数,表示在控制连接中使用的可打印字符(比如,缺省的NVT-ASCII)。在重开始标志中不能使用
例如,要传输6个字符标记,应该按如下发送:
+--------+--------+--------+
|描述符 | 字节记数 |
| = 16| = 6 |
+--------+--------+--------+
+--------+--------+--------+
| 标记 | 标记 | 标记 |
| 8 位 | 8 位 | 8 位 |
+--------+--------+--------+
+--------+--------+--------+
| 标记 | 标记 | 标记 |
| 8 位 | 8 位 | 8 位 |
+--------+--------+--------+
1 7 8 8n字节的字节串d(1),...,d(n)
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|0| n | | d(1) | ... | d(n) |
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
^ ^
|---n个字节---|
2 6 8一串长度n的填充字节可以压缩成一个字节,填充字节与表示类型有关。如果类型是ASCII或EBCDIC,填充字节是
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|1 0| n | | d |
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
2 6
+-+-+-+-+-+-+-+-+
|1 1| n |
+-+-+-+-+-+-+-+-+
转义序列由两个字节组成,第一个字节为转义字节(全0)第二个字节包括块模式中定义的描述码。这里的描述码与块模式中的描述码意义相同,并对后面的字节串有效。
压缩模式适用于在传输大数据时以较小的CPU代价换来一定的网络带宽。最适合用在减少RJE主机产生的打印文件大小。
这里并没有提供是否在传输中存在丢失字节或者数据包混乱的方法。这个级别的错误由TCP控制。但必须提供一个重开始的方法来应对系统错误(包括主机、FTP过程、或网络的失败)。
重开始过程只定义在块模式和压缩模式下。它要求数据发送者在数据流中插入一个特殊的标记。这个标记信息只对发送方有意义,但必须由缺省或协商的控制连接语
言(ASCII或EBCDIC)中的可打印字符组成。标记要表示一个位记数,一个记录记数,或者可以表示数据检查点的信息。数据的接收方,如果要实现重开
始过程,将用此标记指定数据位置,并将此信息返回给用户。
系统失败的情况下,用户可以用标记的位置信息重新开始传送过程。下面的例子演示了重开始过程的使用。
数据的发送方在数据流中的适当的位置插入了一个标记块。接收主机在它的文件系统中标记对应的数据点,并直接或用110号控制连接响应(取决于发送方是谁)
向用户传达最后的标记信息。在系统失败时,用户或控制过程使用重开始命令并以标记信息为其参数来重开始传输。重开始命令通过控制连接传输,后面跟上系统失
败时正在执行的命令(比如RETR,STOR或LIST)。