设为首页 收藏本站
查看: 1578|回复: 0

FTP协议技术文档

[复制链接]

尚未签到

发表于 2015-5-26 11:56:57 | 显示全部楼层 |阅读模式
浅析FTP的工作原理


摘要

通过阅读本文,您可以了解到FTP的基本的工作原理。作者以建立FTP连接到断开FTP连接的方式详细介绍了FTP会话全过程。如果您对PORT模式或者PASV模式的FTP工作原理有些疑惑,相信本文能使您了解更多的细节,使您更加从容的面对企业的网络流量以及安全的管理,特别是如果您的企业正准备在企业内部署ISA Server 2000,或许会给您发布内部服务器带来帮助!


目录



    FTP协议概述
    PORT模式
    PASV模式
    比较分析
  • 图示



FTP协议概述



起初, FTP并不是应用于IP网络上的协议,而是ARPANEt网络中计算机间的文件传输协议, ARPANET是美国国防部组建的老网络,于1960-1980年使用。在那时, FTP的主要功能是在主机间高速可靠地传输文件。目前FTP仍然保持其可靠性,即使在今天,它还允许文件远程存取。这使得用户可以在某个系统上工作,而将文件存贮在别的系统。例如,如果某用户运行Web服务器,需要从远程主机上取得HTML文件和CGI程序在本机上工作,他需要从远程存储站点获取文件(远程站点也需安装Web服务器)。当用户完成工作后,可使用FTP将文件传回到Web服务器。采用这种方法,用户无需使用Telnet登录到远程主机进行工作,这样就使Web服务器的更新工作变得如此的轻松。

FTP是TCP/IP的一种具体应用,它工作在OSI模型的第七层,TCP模型的第四层上,即应用层,使用TCP传输而不是UDP,这样FTP客户在和服务器建立连接前就要经过一个被广为熟知的"三次握手"的过程,它带来的意义在于客户与服务器之间的连接是可靠的,而且是面向连接,为数据的传输提供了可靠的保证。

下面,让我们来看看,一个FTP客户在和服务器连接是怎么样的一个过程(以标准的FTP端口号为例)。

首先,FTP并不像HTTP协议那样,只需要一个端口作为连接(HTTP的默认端口是80,FTP的默认端口是21),FTP需要2个端口,一个端口是作为控制连接端口,也就是21这个端口,用于发送指令给服务器以及等待服务器响应;另一个端口是数据传输端口,端口号为20(仅PORT模式),是用来建立数据传输通道的,主要有3个作用

    从客户向服务器发送一个文件。
    从服务器向客户发送一个文件。
  • 从服务器向客户发送文件或目录列表。


其次,FTP的连接模式有两种,PORT和PASV。PORT模式是一个主动模式,PASV是被动模式,这里都是相对于服务器而言的。为了让大家清楚的认识这两种模式,朗月繁星分别举例说明。


PORT模式



当FTP客户以PORT模式连接服务器时,他动态的选择一个端口号(本次试验是6015)连接服务器的21端口,注意这个端口号一定是1024以上的,因为1024以前的端口都已经预先被定义好,被一些典型的服务使用,当然有的还没使用,保留给以后会用到这些端口的资源服务。当经过TCP的三次握手后,连接(控制信道)被建立(如图1和图2)。现在用户要列出服务器上的目录结构(使用ls或dir命令),那么首先就要建立一个数据通道,因为只有数据通道才能传输目录和文件列表,此时用户会发出PORT指令告诉服务器连接自己的什么端口来建立一条数据通道(这个命令由控制信道发送给服务器),当服务器接到这一指令时,服务器会使用20端口连接用户在PORT指令中指定的端口号,用以发送目录的列表(如图3)。当完成这一操作时,FTP客户也许要下载一个文件,那么就会发出get指令,请注意,这时客户会再次发送PORT指令,告诉服务器连接他的哪个"新"端口,你可以先用netstat -na这个命令验证,上一次使用的6044已经处于TIME_WAIT状态(如图4)。当这个新的数据传输通道建立后(在微软的系统中,客户端通常会使用连续的端口,也就是说这一次客户端会用6045这个端口),就开始了文件传输的工作。


PASV模式



然而,当FTP客户以PASV模式连接服务器时,情况就有些不同了。在初始化连接这个过程即连接服务器这个过程和PORT模式是一样的,不同的是,当FTP客户发送ls、dir、get等这些要求数据返回的命令时,他不向服务器发送PORT指令而是发送PASV指令,在这个指令中,用户告诉服务器自己要连接服务器的某一个端口,如果这个服务器上的这个端口是空闲的可用的,那么服务器会返回ACK的确认信息,之后数据传输通道被建立并返回用户所要的信息(根据用户发送的指令,如ls、dir、get等);如果服务器的这个端口被另一个资源所使用,那么服务器返回UNACK的信息,那么这时,FTP客户会再次发送PASV命令,这也就是所谓的连接建立的协商过程。为了验证这个过程我们不得不借助CUTEFTP Pro这个大家经常使用的FTP客户端软件,因为微软自带的FTP命令客户端,不支持PASV模式。虽然你可以使用QUOTE PASV这个命令强制使用PASV模式,但是当你用ls命令列出服务器目录列表,你会发现它还是使用PORT方式来连接服务器的。现在我们使用CUTEFTP Pro以PASV模式连接服务器(如图5),请注意连接LOG里有这样几句话:


COMMAND:>PASV
227 Entering Passive Mode (127,0,0,1,26,108)
COMMAND:>LIST
STATUS:>  Connecting ftp data socket 127.0.0.1: 6764...
125 Data connection already open; Transfer starting.
226 Transfer complete.

其中,

227 Entering Passive Mode (127,0,0,1,26,80). 代表客户机使用PASV模式连接服务器的26x256+108=6764端口。(当然服务器要支持这种模式)

125 Data connection already open; Transfer starting.说明服务器的这个端口可用,返回ACK信息。

再让我们看看用CUTEFTP Pro以PORT模式连接服务器的情况。其中在LOG里有这样的记录:


COMMAND:>PORT 127,0,0,1,28,37
200 PORT command successful.
COMMAND:>LIST
150 Opening ASCII mode data connection for /bin/ls.
STATUS:>  Accepting connection: 127.0.0.1:20.
226 Transfer complete.
STATUS:>  Transfer complete.

其中,

PORT 127,0,0,1,28,37告诉服务器当收到这个PORT指令后,连接FTP客户的28x256+37=7205这个端口。

Accepting connection: 127.0.0.1:20表示服务器接到指令后用20端口连接7205端口,而且被FTP客户接受。


比较分析



在这两个例子中,请注意: PORT模式建立数据传输通道是由服务器端发起的,服务器使用20端口连接客户端的某一个大于1024的端口;在PASV模式中,数据传输的通道的建立是由FTP客户端发起的,他使用一个大于1024的端口连接服务器的1024以上的某一个端口。如果从C/S模型这个角度来说,PORT对于服务器来说是OUTBOUND,而PASV模式对于服务器是INBOUND,这一点请特别注意,尤其是在使用防火墙的企业里,比如使用微软的ISA Server 2000发布一个FTP服务器,这一点非常关键,如果设置错了,那么客户将无法连接。

最后,请注意在FTP客户连接服务器的整个过程中,控制信道是一直保持连接的,而数据传输通道是临时建立的。

在本文中,朗月繁星把重点放到了FTP的连接模式,没有涉及FTP的其他内容,比如FTP的文件类型(Type),格式控制(Format control)以及传输方式(Transmission mode)等。不过这些规范大家可能不需要花费过多的时间去了解,因为现在流行的FTP客户端都可以自动的选择正确的模式来处理,对于FTP服务器端通常也都做了一些限制,如下

    类型:A S C I I或图像。
    格式控制:只允许非打印。
    结构:只允许文件结构。
  • 传输方式:只允许流方式


至于这些内容,限于篇幅朗月繁星在这里就不想再介绍了。希望这篇文章能对大家有些帮助,特别是正在学习ISA Server2000的朋友和一些对FTP不很了解的朋友。

OK,就此驻笔了,希望大家与我交流。


图示


http://www.microsoft.com/china/community/images/TechArticleImages/ftpprinciple_1.gif




图1:FTP客户使用FTP命令建立于服务器的连接
http://www.microsoft.com/china/community/images/TechArticleImages/ftpprinciple_2.gif




图2:用netstat命令查看,控制信道被建立在客户机的6015和服务器的20端口
http://www.microsoft.com/china/community/images/TechArticleImages/ftpprinciple_3.gif




图3:ls命令是一个交互命令,它会首先与服务器建立一个数据传输通道。经验证本次试验客户机使用6044端口
http://www.microsoft.com/china/community/images/TechArticleImages/ftpprinciple_4.gif




图4:使用netstat命令验证上一次使用ls命令建立的数据传输通道已经关闭
http://www.microsoft.com/china/community/images/TechArticleImages/ftpprinciple_5_1.gif




图5:使用CUTEFTP Pro以PASV模式连接服务器点此可看详图






作者:吕劼(朗月繁星) aloneV@163.com

2002年10月24日

FTP协议规范:


传输控制协议(Transmission Control Protocol, TCP)
TCP协议主为了在主机间实现高可靠性的包交换传输协议。本文将描述协议标准和实现的一些方法。因为计算机网络在现代社会中已经是不可缺少的了,TCP协议主要在网络不可靠的时候完成通信,对军方可能特别有用,但是对于政府和商用部门也适用。TCP是面向连接的端到端的可靠协议。它支持多种网络应用程序。TCP对下层服务没有多少要求,它假定下层只能提供不可靠的数据报服务,它可以在多种硬件构成的网络上运行。下面的图是TCP在层次式结构中的位置,它的下层是IP协议,TCP可以根据IP协议提供的服务传送大小不定的数据,IP协议负责对数据进行分段,重组,在多种网络中传送。

TCP的上面就是应用程序,下面是IP协议,上层接口包括一系列类似于操作系统中断的调用。对于上层应用程序来说,TCP应该能够异步传送数据。下层接口我们假定为IP协议接口。为了在并不可靠的网络上实现面向连接的可靠的传送数据,TCP必须解决可靠性,流量控制的问题,必须能够为上层应用程序提供多个接口,同时为多个应用程序提供数据,同时TCP必须解决连接问题,这样TCP才能称得上是面向连接的,最后,TCP也必须能够解决通信安全性的问题。
网络环境包括由网关(或其它设备)连接的网络,网络可以是局域网也可以是一些城域网或广域网,但无论它们是什么,它们必须是基于包交换的。主机上不同的协议有不同的端口号,一对进程通过这个端口号进行通信。这个通信不包括计算机内的I/O操作,只包括在网络上进行的操作。网络上的计算机被看作包传送的源和目的结点。特别应该注意的是:计算机中的不同进程可能同时进行通信,这时它们会用端口号进行区别,不会把发向A进程的数据由B进程接收的。
进程为了传送数据会调用TCP,将数据和相应的参数传送给TCP,于是TCP会将数据传送到目的TCP那里,当然这是通过将TCP包打包在IP包内在网络上传送达到的。接收方TCP在接收到数据后会通信上层应用程序,TCP会保证接收数据顺序的正确性。虽然下层协议可能不会保证顺序是正确的。这里需要说明的是网关在接收到这个包后,会将包解开,看看是不是已经到目的地了,如果没有到,应该走什么路由达到目的地,在决定后,网关会根据下一个网络内的协议情况再次将TCP包打包传送,如果需要,还要把这个包再次分成几段再传送。这个落地检查的过程是一个耗时的过程。从上面,我们可以看出TCP传送的基本过程,当然具体过程可能要复杂得多。
在实现TCP的主机上,TCP可以被看成是一个模块,和文件系统区别不大,TCP也可以调用一些操作系统的功能,TCP不直接和网络打交道,控制网络的任务由专门的设备驱动模块完成。TCP只是调用IP接口,IP向TCP提供所有TCP需要的服务。通过下图我们可以更清楚地看到TCP协议的结构。

上面已经说过了,TCP连接是可靠的,而且保证了传送数据包的顺序,保证顺序是用一个序号来保证的。响应包内也包括一个序列号,表示接收方准备好这个序号的包。在TCP传送一个数据包时,它同时把这个数据包放入重发队列中,同时启动记数器,如果收到了关于这个包的确认信息,将此包从队列中删除,如果计时超时则需要重新发送此包。请注意,从TCP返回的确认信息并不保证最终接收者接收到数据,这个责任由接收方负责。
每个用于传送TCP的通道都有一个端口标记,因为这个标记是由每个TCP终端确定的,因此TCP可能不唯一,为了保证这个数值的唯一,要使用网络地址和端口号的组合达到唯一标识的目的,我们称这个为了套接字(Socket),一个连接由连接两端的套接字标识,本地的套接字可能和不同的外部套接字通信,这种通信是全双工的。
通过向本地端口发送OPEN命令及外部套接字参数建立连接,TCP返回一个标记这个连接的名称,以后如果用户需要使用这个名称标记这个连接。为了保存这个连接的信息,我们假设有一个称为传输控制块(Transmission Control Block,TCB)的东西来保存。OPEN命令还指定这个连接的建立是主动请求还是被动等待请求。下面我们要涉及具体的功能了,TCP段以internet数据报的形式传送。IP包头传送不同的信息域,包括源地址和目的地址。TCP头跟在internet包头后面,提供了一些专用于TCP协议的信息。下图是TCP包头格式图:

源端口:16位;
目的端口:16位
序列码:32位,当SYN出现,序列码实际上是初始序列码(ISN),而第一个数据字节是ISN+1;
确认码:32位,如果设置了ACK控制位,这个值表示一个准备接收的包的序列码;
数据偏移量:4位,指示何处数据开始;
保留:6位,这些位必须是0;
控制位:6位;
窗口:16位;
校验位:16位;
优先指针:16位,指向后面是优先数据的字节;
选项:长度不定;但长度必须以字节记;选项的具体内容我们结合具体命令来看;
填充:不定长,填充的内容必须为0,它是为了保证包头的结合和数据的开始处偏移量能够被32整除;
 
我们前面已经说过有一个TCB的东西了,TCB里有存储了包括发送方,接收方的套接字,用户的发送和接收的缓冲区指针等变量。除了这些还有一些变量和发送接收序列号有关:
发送序列变量
SND.UNA - 发送未确认
SND.NXT - 发送下一个
SND.WND - 发送窗口
SND.UP - 发送优先指针
SND.WL1 - 用于最后窗口更新的段序列号
SND.WL2 - 用于最后窗口更新的段确认号
ISS - 初始发送序列号
 
接收序列号
RCV.NXT - 接收下一个
RCV.WND - 接收下一个
RCV.UP - 接收优先指针
IRS - 初始接收序列号
下图会帮助您了解发送序列变量间的关系:




[table=300]

http://longen.org/S-Z/details~z/TCPDetail-4.gifhttp://longen.org/S-Z/details~z/TCPDetail-5.gif


当前段变量
SEG.SEQ - 段序列号
SEG.ACK - 段确认标记
SEG.LEN - 段长
SEG.WND - 段窗口
SEG.UP - 段紧急指针
SEG.PRC - 段优先级
连接进程是通过一系列状态表示的,这些状态有:LISTEN,SYN-SENT,SYN-RECEIVED,ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2,CLOSE-WAIT,CLOSING,LAST-ACK,TIME-WAIT和 CLOSED。CLOSED表示没有连接,各个状态的意义如下:
LISTEN - 侦听来自远方TCP端口的连接请求;
SYN-SENT - 在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED - 代表一个打开的连接,数据可以传送给用户;
FIN-WAIT-1 - 等待远程TCP的连接中断请求,或先前的连接中断请求的确认;
FIN-WAIT-2 - 从远程TCP等待连接中断请求;
CLOSE-WAIT - 等待从本地用户发来的连接中断请求;
CLOSING - 等待远程TCP对连接中断的确认;
LAST-ACK - 等待原来发向远程TCP的连接中断请求的确认;
TIME-WAIT - 等待足够的时间以确保远程TCP接收到连接中断请求的确认;
CLOSED - 没有任何连接状态;
TCP连接过程是状态的转换,促使发生状态转换的是用户调用:OPEN,SEND,RECEIVE,CLOSE,ABORT和STATUS;传送过来的数据段,特别那些包括以下标记的数据段SYN,ACK,RST和FIN;还有超时,上面所说的都会时TCP状态发生变化。
 
下面的图表示了TCP状态的转换,但这图中没有包括错误的情况和错误处理,不要把这幅图看成是总说明了。

 
3.3. 序列号
请注意,我们在TCP连接中发送的字节都有一个序列号。因为编了号,所以可以确认它们的收到。对序列号的确认是累积性的,也就是说,如果用户收到对X的确认信息,这表示在X以前的数据(不包括X)都收到了。在每个段中字节是这样安排的:第一个字节在包头后面,按这个顺序排列。我们需要认记实际的序列空间是有限的,虽然很大,但是还是有限的,它的范围是0到2的32次方减1。我想熟悉编程的一定知道为什么要在计算两个段是不是相继的时候要使用2的32次方为模了。TCP必须进行的序列号比较操作种类包括以下几种:
(a) 决定一些发送了的但未确认的序列号;
(b) 决定所有的序列号都已经收到了;
(c) 决定下一个段中应该包括的序列号。
对于发送的数据TCP要接收确认,处理确认时必须进行下面的比较操作:
SND.UNA = 最老的确认了的序列号;
SND.NXT = 下一个要发送的序列号;
SEG.ACK = 接收TCP的确认,接收TCP期待的下一个序列号;
SEG.SEQ = 一个数据段的第一个序列号;
SEG.LEN = 数据段中包括的字节数;
SEG.SEQ+SEG.LEN-1 = 数据段的最后一个序列号。
请注意下面的关系:
SND.UNA < SEG.ACK =< SND.NXT
如果一个数据段的序列号小于等于确认号的值,那么整个数据段就被确认了。而在接收数据时下面的比较操作是必须的:
RCV.NXT = 期待的序列号和接收窗口的最低沿;
RCV.NXT+RCV.WND-1 = 最后一个序列号和接收窗口的最高沿;
SEG.SEQ = 接收到的第一个序列号;
SEG.SEQ+SEG.LEN-1 = 接收到的最后一个序列号;
 
上面几个量有如下关系:
RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND 或 RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND
测试的第一部分是检查数据段的开始部分是否在接收窗口中,第二部分是检查数据段的结束部分是否也在接收窗口内;上面两个检查通过任何一个就说明它包括窗口要求的数据。实际中的情况会更复杂一些,因为有零窗口和零数据段长,因此我们有下面四种情况:



段长度




接收窗口



测试



0




0



SEG.SEQ = RCV.NXT



0




>0



RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND



>0




0



不可接受



>0




>0



RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND或RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND




请注意接收窗口的大小可以为零,在窗口为零时它只用来接收ACK信息,因此对于一个TCP来说,它可以使用零大小窗口在发送数据的同时接收数据。即使接收窗口的大小为零,TCP必须处理所有接收到信息的RST和URG域。
我们也应用计数的方式保护了一些特定的控制信息,这是通过隐式地使用一些控制标记使数据段能够可靠地重新发送(或确认)为达到的。控制信息并不在段数据空间中传送,因此,我们必须采用隐式指定序列号进行控制。SYN和FIN是需要保护的控制量,这两个控制量也只在连接打开和关闭时使用。SYN被认为是在第一个实际数据之间的数据,而FIN是最后一个实际数据之后的数据。段长度(SEG.LEN)包括数据和序列号空间,如果出现了SYN,那么SEG.SEQ是SYN的序列号。
初始序列号选择
协议对于特定连接被重复使用没有什么限制。连接是由一对套接字定义的。新的连接实例被定义为连接的另一次恢复,这就带来了问题:TCP如果确定多个数据段是从以前连接的另一次恢复中取得的呢?这个问题在连接迅速打开和关闭,或因为内存原因被关闭然后又迅速建立后显示特别突出。
为了避免混乱,用户必须避免因此恢复使用某一连接,而使序列号发生混乱。我们必须保证序列号的正确性,即使TCP失败,根本不知道以前的序列号是什么的情况下也要保证序列号的正确性。当新的连接被创建时,产生一个新的初始序列号(ISN)产生子,它用来选择一个新的32位ISN。产生子和32位时钟的低度位字节相关,低位字节的刷新频率大概是4微秒,因此ISN的循环时间大概是4.55小时。因此我们把网络包的最长生存时间(MSL)小于4.55小时,因此我们可以认为ISN是唯一的。对于每个连接都有发送序列号和接收序列号,初始发送序列号(ISS)由发送TCP选择,而初始接收序列号是在连接建立过程中产生的。
对于将要连接或初始化的连接,两个TCP必须和对方的初始序列号同步。这通过交换一个控制位SYN和初始序列号完成。我们把带有SYN的数据段称为"SYNs"。同步的获得过程这里就不重复了,每方必须发送自己的序列号并返回对对方序列号的确认。
1) A --> B SYN 本方序列号是X
2) A  local connection name
我们假定本地TCP注意到它所服务的进程标记,而且将检查进程的认证。因实现不同,本地网络和源地址的TCP认证可能由TCP进行也可以由下层协议进行(如IP协议)。这些考虑主要是基于安全性的考虑。
如果active/passive标记设置为passive,TCP会检测到达的连接请求,它是被动的,被动的连接可以有一个完全指定的外套接字用于等待特定的连接或未指定的外套接字来等待任何呼叫。一个完全定义的被动呼叫可以通过执行一系列的SEND命令而变为主动的。创建一个传输控制块(TCB),其中一部分参数是由OPEN命令参数而来。在主动OPEN时,TCP会立刻开始同步连接。如果给出参数timeout,会允许呼叫者应用于所有TCP数据。如果在timeout规定的时间内还未把数据送到目的地,就关闭连接,一般的默认值是5分钟。
参数precedence或security/compartment是用于规范用户对某一连接的安全性的,如果没有指定则使用默认值。TCP会匹配这两个参数,只有在security/compartment一致而且接收到的precedence小于等于要求的precedence时才会打开连接。当连接的precedence大于要求的值时,从接收到的数据段中取得这一值,并在连接中一直使用这个比较大的值。具体实现时可以给用户权力控制precedence的决定过程。例如,用户可以要求precedence必须安全一致,或在提升precedence时要通知用户。
本地连接名(local connection name)由TCP返回用户,它可以代替标记一个连接。
Send
格式:SEND (local connection name, buffer address, byte count, PUSH flag, URGENT flag [,timeout])
这个命令使指定缓冲区内的数据发向指定连接,如果连接未打开则返回一个错误,一些实现中可能在打开连接以前调用SEND,由SEND自动打开连接。如果设置了PUSH标记,数据必须立刻传送给接收者,而且PUSH位在缓冲区中的最后一个段是必须设置。如果没有设置,此数据段就会因为效率的考虑而和下一个SEND命令传送的数据一起传送。如果设置了URGENT标记,那就必须象上面所述的一样紧急处理。传送方设置的URGENT数目不一定非要等于通知接收方用户的次数。
如果在OPEN中没有指定外套接字,那缓冲区数据会被发送到隐式外套接字。未使用外套接字打开连接的用户仍然可以SEND,而不用知道外套接字地址。但是,如果在指定外套接字前进行SEND,则会出错。用户可以使用STATUES确定连接状态。如果指定了timeout,对于当前连接的当前用户timeout会更改为新的连接。
最简单的实现方法就是在没有把数据发送完毕以前,SEND不把控制权交给发送进程,但是这样可能会造成死锁(例如,双方都试图SEND,而不准备RECEIVE),效率也不好。好的实现方法是在发送一段数据后返回控制权给发送进程,当然如果能够多个SEND同时发送,那更好不过了。有多个SEND需要服务时一般采取先来先服务。
对于本地来说,我们现在假定的是SEND在发送数据后会产生类似中断的东西告诉发送进程数据发送的情况;当然SEND也可以在发送完后立刻告知进行数据发送的情况。我们可以乐观地认为发送是成功的,如果发送失败,连接会因为超时而关闭。在实现中,即使是同步返回情况,也需要一些异步信号,但这些异步信号是用于处理连接的,而不是用于处理数据发送的。既然允许多个SEND同时工作,因此有必要区别返回的信息是哪一个SEND的。具体的情况下面会讨论到。
Receive
格式: RECEIVE (local connection name, buffer address, byte count) -> byte count, urgent flag, push flag
此命令分配一个接收缓冲区给指定的连接。如果下面不是一个OPEN命令或者此调用进行未被授权使用此连接返回错误。最简单的实现方法是在缓冲区没有填充完以前不返回控制权,但这样可能会造成严重的死锁。更复杂的实现方法允许同时存在多个RECEIVE,这样会提高效率。这样是在控制复杂的情况下取得了高效率。
如果在PUSH之前的数据已经填满缓冲区,那么对于RECEIVE的响应中就不用设置PUSH位了。缓冲区会容纳尽可能多的数据,如果在缓冲区填充满以前看到PUSH位,将返回缓冲区中的数据并设置PUSH。在处理紧急状态时,如果有URGENT标记,还有紧急数据;如果没有URGENT标记了,就返回所有紧急数据,用户也离开紧急状态。请注意,在紧急指针指向的点以后的那些数据不能和紧急数据一起返回,即使它们在同一个缓冲区内,当然,如果用户指定要这么做例外。
为了区别多个RECEIVE并保证缓冲区不被充满,返回的数据中也要包括缓冲区指针和一个计数器指明现在接收了多少数据。RECEIVE可以有自己专用了缓冲区,也可以和用户共享一个缓冲区。
Close
格式: CLOSE (本地连接名)
此命令关闭连接,如果连接未打开,或未授权可以关闭连接返回错误。在关闭的时候应该注意正常关闭,让所有的发送都发送完数据,也可以如上所说在CLOSE后面加上几个SEND,这就要求用户在收到CLOSE后仍然要进行接收。因此,CLOSE意指&#8220;我没有更多的数据要发了&#8221;,并不代表&#8220;我不再发送任何数据了&#8221;。关闭方也可能在超时前不能发出所有数据,这种情况下,要由CLOSE转入ABORT状态。用户可以自己决定在任何时间关闭连接,也可以根据TCP返回的提示关闭。因此关闭操作要和外TCP进行通信,因此在关闭状态可能要呆一会儿,在CLOSE没有返回前调用打开,会返回错误。
Status
格式: STATUS (本地连接名) -> status data
这个命令和具体的实现有关,而且有可能会有负作用。返回的信息通常来自有连接相关的TCB。返回的数据块中包括下面的信息:本地套接字,外套接字,本地连接名,接收窗口,发送窗口,连接状态,等待确认的缓冲区数,等待接收的缓冲区数,紧急状态,优先级,security/compartment和传输超时。因此实现不同,所以上述数据项中可能有几项没有意义或根本不存在。如果调用进程没有被授权使用这一连接,返回错误。这一点会防止未被授权的进程获得连接状态。
Abort
格式: ABORT (本地连接名)
此命令中止所有SEND和RECEIVE,删除TCB,将发送特殊的RESERT信息到对方TCP。具体的返回信息会因实现不同而不同。
TCP到用户信息
假定操作系统提供一种可以使TCP异步传送信息到用户程序的机制。当TCP确实通知用户程序时会返回一些特定的信息。通常在这些信息中也会有错误信息,在其它情况下会有关于完成SEND或RECEIVE或其它用户调用的相关信息。会提供下面的几种消息:
本地连接名 都提供
响应串 都提供
缓冲区地址 发送和接收
字节记数 接收
Push标记 接收
Urgent标记 接收
 
TCP和下层接口
TCP实际上调用下层服务才能在网络上传输数据,在互联网上我们通常认为TCP的下层是IP协议。如果下层是IP层,它提供一些类于服务类型和生存时间的参数。TCP使用这些参数的如下设置:
Type of Service = Precedence: routine, Delay: normal, Throughput: normal, Reliability: normal;或是数字00000000。
Time to Live = 一分钟,或是数字00111100。
请注意:假定的最大数据段的生存时间为2分钟,这里人为指定为1分钟。
如果下层是IP而且使用源地址路由,接口必须允许路由信息的通信。这对建立连接和进行路由是十分重要的。当然也可以不使用IP协议作为TCP的底层协议,但无论下层协议是什么,都必须提供源地址,目的地址和协议域,以及一些决定TCP长度的域,总之一句话,要能够提供类似于IP的功能。
3.9. 事件处理
下面说明的过程是可能的实现,其它实现和本例的过程可能有一点点不同,但只在细节,而决不在结果。TCP的活动可以总结为对事件的响应。事件可以分为三类:用户调用,接收数据段和超时。下面描述的是TCP对具体事件的响应,在许多情况下,相关的动作(响应)要和连接状态相关。
用户调用的有:
OPEN
SEND
RECEIVE
CLOSE
ABORT
STATUS
接收数据段的有:
SEGMENT ARRIVES
超时的有:
USER TIMEOUT
RETRANSMISSION TIMEOUT
TIME-WAIT TIMEOUT
TCP对用户的响应可能是立即的也可能是延时的。错误信息以字符串的形式给出。下面就是一个具体的错误信息:error: connection not open。另外,请记住序列号空间大小为2的32次方。处理数据段的顺序为首先接收,再检查序列号,如果是要接收的就放入接收队列。另外,没有说明状态转移时,TCP保持原来的状态。
OPEN调用
CLOSED状态
创建新的TCB保存连接状态信息,填充本地套接字标记,外套接字,优先级,security/compartment和用户超时信息。注意一部分外套接字在被动OPEN中可能未说明。如果是主动的,而外套接字未指定,返回"error: foreign socket unspecified";如果是主动的,而外套接字指定了,发送一个SYN数据段。选择初始发送序列号ISS。SYN数据段的格式如下,设置SND.UNA为ISS,SND.NXT为ISS+1,进行SYN-SENT状态,然后返回。
如果调用者不能访问指定的本地套接字,返回"error: connection illegal for this process"。如果没有空间接收新的连接,返回"error: insufficient resources"。
LISTEN状态
如果处于主动状态,指定了外套接字,可以将连接从被动改为主动,并选择ISS。发送一个SYN数据段,设置SND.UNA为ISS,SND.NXT为ISS+1。进入SYN-SENT状态。和SEND一起的数据可以和SYN数据段一起发送,也可以在进入ESTABLISHED状态后发送。如果没有空间接收请求,返回"error: insufficient resources"。如果未指定外套接字,返回"error: foreign socket unspecified"。如果处于以下状态:SYN-SENT状态,SYN-RECEIVED,ESTABLISHED状态,FIN-WAIT-1状态,FIN-WAIT-2状态,CLOSE-WAIT状态,CLOSING状态,LAST-ACK状态或TIME-WAIT状态时返回"error: connection already exists"。
SEND调用
CLOSED状态
如果用户无权访问连接,返回"error: connection illegal for this process"。否则返回"error: connection does not exist"。
LISTEN状态
如果指定了外套接字,可以将连接从被被动改为主动,选择一个ISS。发送SYN数据段,设置SND.UNA为ISS,SND.NXT为ISS+1。进入SYN-SENT状态。和SEND一起的数据可以和SYN数据段一起发送,也可以在进入ESTABLISHED状态后发送。如果没有空间接收请求,返回"error: insufficient resources",如果未指定外套接字,则返回"error: foreign socket unspecified"。
SYN-SENT状态和SYN-RECEIVED时
在进入ESTABLISHED状态后将需要传送的数据加入队列。如果队列已无空间,则返回"error: insufficient resources"。
ESTABLISHED状态和CLOSE-WAIT状态
将缓冲区分段,发送缓冲区数据,并使它带有确认值RCV.NXT。如果没有空间保存缓冲区,则返回"error: insufficient resources"。如果设置了紧急标记,那么SND.UP  ISS,改变连接状态为ESTABLISHED,形成下面格式的ACK段并发送: 。队列中用于发送的数据的控制信息也一起发送,如果段中没有数据或控制信息,则进行第六步,否则返回。如果SND.UNA > ISS不成立,形成SYN,ACK段,格式如下:,并发送它。如果在段中没有数据或控制信息,待进入ESTABLISHED状态后再进行处理。
第五步,如果SYN或RST位没有设置,抛弃数据段返回。
下来我们来看看其它状态。首先应该检查序列号。在下面状态下
SYN-RECEIVED状态
ESTABLISHED状态
FIN-WAIT-1状态
FIN-WAIT-2状态
CLOSE-WAIT状态
CLOSING状态
LAST-ACK状态
TIME-WAIT状态
段按顺序处理,首先抛弃重复的段,对于以后的处理要根据SEG.SEQ的大小进行。如果有的段内的新老内容重叠在一起,那只用处理新的那一部分。下面是对接收到的数据的可接受性测试中的四种情况:




段长度




接收窗口




测试




0




0




SEG.SEQ = RCV.NXT




0




>0




RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND




>0




0




不接受




>0




>0




RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND或RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND




如果RCV.WND = 0,除了合法的ACK,URG和RST段外拒绝其它的数据段。如果接收到的数据段不可接受,应该返回一个应答,格式如下:。在发送完应答后,抛弃不可接受的数据段,然后返回。
第二步检查RST位。
如果处于SYN-RECEIVED 状态时,而且处于设置了RST的情况下,如果连接以被动OPEN开始,将连接返回到LISTEN状态,不需要通知用户;如果连接以主动OPEN打开,拒绝连接,并通知用户"connection refused"。在上面任何一种情况下,所有在重发队列中的数据都要删除。在主动OPEN的那种情况下,进入CLOSED状态,删除TCB然后返回。
如果处于ESTABLISHED,FIN-WAIT-1,FIN-WAIT-2或CLOSE-WAIT状态时,而且RST已经设置,那么任何存在的RECEIVE和SEND都会收到"reset"。所有队列中的数据段都应该立即发送。用户也会收到"connection reset"。进入CLOSED状态,删除TCB并返回。
如果处于CLOSING状态,LAST-ACK状态或TIME-WAIT状态,而且RST已经设置,进入CLOSED状态,删除TCB并返回。
检查安全和优先级
在SYN-RECEIVED状态下
如果段中的security/compartment和优先级和TCB中的不匹配,发送RST并返回。
在ESTABLISHED状态下
如果段中的security/compartment和优先级和TCB中的不匹配,发送RST ,所有存在的RECEIVE和SEND接收到"reset",立即发送所有队列中的数据段,用户接收到"connection reset"。进入CLOSED状态,删除TCB并返回。
第四步检查SYN位,如果连接处于以下状态
SYN-RECEIVED
ESTABLISHED状态
FIN-WAIT STATE-1
FIN-WAIT STATE-2
CLOSE-WAIT状态
CLOSING状态
LAST-ACK状态
TIME-WAIT状态
如果SYN在窗口中就是错误,发送RST,任何存在的RECEIVE和SEND收到"reset",所有在队列中的数据段立即发送,用户也接收到"connection reset",进入CLOSED状态,删除TCB并返回。如果SYN未在窗口中,这一步不会发生。
第五步检查ACK域
如果ACK位关闭,抛弃数据段返回。如果ACK域打开的情况下,如果连接处于
SYN-RECEIVED状态时
如果SND.UNA =< SEG.ACK =< SND.NXT,进入ESTABLISHED状态。如果段的确认消息不可接受,形成如下形式的RST并发送:

ESTABLISHED状态时
如果SND.UNA < SEG.ACK =< SND.NXT,设置SND.UNA  SND.NXT),那么可以发送ACK,抛弃数据段并返回。
如果SND.UNA < SEG.ACK =< SND.NXT,应该更新发送窗口。如果(SND.WL1 < SEG.SEQ)或(SND.WL1 = SEG.SEQ且SND.WL2 =< SEG.ACK),设置SND.WND

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-70879-1-1.html 上篇帖子: BizTalk Server 2010新功能介绍(四):基于安全连接的FTP适配器 下篇帖子: 在.Net中使用FTP(08.12.19新增源代码)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表