FTP服务器项目的一些整理

几个月前按照网上的教程写了一个FTP的服务器,现在回头整理一下里面的一些知识。


FTP简介


FTP是文件传输协议(File Transfer Protocol),工作在TCP/IP协议族的应用层,其传输层使用的是TCP协议,它是基于客户/服务器模式工作的(C/S架构),TCP/IP协议中,FTP标准命令TCP端口号为21,Port方式数据端口为20。


FTP的两种传输方式


FTP有两种传输方式:ASCII文件传输模式和二进制文件传输模式。


ASCII文件和二进制文件的区别


ASCII文件也称为文本文件,ASCII文件和二进制文件在物理上没有本质的区别,他们都是由一系列的比特位组成的,他们的差别仅仅在于逻辑之上,或者说系统对他们的解析方法不同。ASCII文件由ASCII字符构成,一个ASCII字符有7个比特位,最高位总是0,而二进制文件的最高位有可能就是1。另一个差别是换行符,不同系统对换行符的表示方式不同,windows下换行符是\r\n,linux下的换行符是\n,其他的系统可能是其他的方式,ASCII传输方式和二进制传输方式在处理换行符也有所不同。


ASCII传输方式


假定用户正在拷贝的文件包含的简单ASCII码文本,如果在我们使用的系统是windows系统,而运行ftp服务器的远程机器上的系统是Linux,那么使用ASCII传输模式会将\r\n转为\n。反过来,如果我们使用的系统是Linux系统,而运行ftp服务器的远程机器上的系统是Windows,那么使用ASCII传输模式会将\n转为\r\n。也就是说,当文件传输时ftp通常会自动地调整文件的内容以便于把文件解释成另外那台计算机存储文本文件的格式。


 二进制传输模式


使用ASCII传输方式可能会改变我们的文件,但是常常有这样的情况,用户正在传输的文件包含的不是文本文件,它们可能是程序,数据库,字处理文件或者压缩文件(尽管字处理文件包含的大部分是文本,其中也包含有指示页尺寸,字库等信息的非打印字符)。
所以此时我们最好使用二进制传输方式。使用二进制传输时,在拷贝任何非文本文件的时候FTP会逐字拷贝,不会对这些文件进行处理。
  如果在ASCII方式下传输二进制文件,即使不需要也仍会转译。这会使传输稍微变慢 ,也会损坏数据,使文件变得不能用。(在大多数计算机上,ASCII方式一般假设每一字符的第一有效位无意义,因为ASCII字符组合不使用它。如果你传输二进制文件,所有的位都是重要的。)如果你知道这两台机器是同样的,则二进制方式对文本文件和数据文件都是有效的。

FTP的两种工作方式


FTP的连接分为控制连接和数据连接,控制连接用于传输控制命令,是随客户端一同存在的,而数据连接只是短暂存在,每次要发生数据的时候才建立数据连接,数据传输完毕后就断开数据连接。FTP的控制连接总是由客户端想服务器端发起的,而FTP数据连接的建立有两种途径,一种是客户端连接到服务器端,另一种是服务器连接到客户端,这分别对应着FTP的两种工作模式:被动模式和主动模式。主动和被动主要是针对FTP服务器而言的,如果是FTP服务器主动连接到客户端则为主动模式,如果FTP服务器被动地接受客户端的连接请求则是被动模式。


主动模式


FTP主动模式的工作过程如下:首先要建立控制连接通道,客户端向FTP服务器的21端口发起连接,经过3次握手建立控制连接通道,一旦控制连接通道建立之后,双方便可以交换信息了。在需要传输数据的时候,需要创建数据通道,选择工作模式。当选择主动模式时,客户端通过控制连接通道发送一个PORT命令并告知服务器数据连接通道的端口BB,然后服务器就向客户端的BB端口发出连接请求,建立数据连接通道,数据连接通道一旦建立,就可以进行数据的传输,传输完毕之后数据连接就会关闭掉。其示意图如下:

                                              


被动模式


FTP被动模式的工作过程如下:首先也是客户端向服务器端21端口发起连接,经过三次握手建立控制连接通道,

被动模式,需要进行数据传输的时候,客户端要向服务器发送一个PASV表示进行被动传输,即数据通道的建立是由客户端向服务器端发起的,而此时客户端需要知道连接到服务器的哪一个端口,于是服务器向客户端发送被动模式的端口XX,之后客户端向服务器的XX端口发起连接建立数据连接通道。其示意图如下:

                                        

那么FTP的数据连接为什么要分为主动模式和被动模式呢?这个和NAT或防火墙对主被动模式的影响有关。


NAT或防火墙对主被动模式的影响


NAT是Network Address Translation,表示网络地址转换,通过NAT可以将内网私有IP地址转换为公网IP地址,一定程度上解决了公网地址不足的问题。

FTP客户端处于NAT或防火墙之后的主动模式


由于客户端处于局域网之中,无法直接访问公网上的服务器,需要经过NAT服务器(中间那个)进行地址转换。而NAT有一个特征,如果是从内向外发起连接,则可以建立成功(NAT会维护一个IP的表目),如果是从外部发起的连接,则无法建立连接。
开始时客户端想服务器发起连接建立控制连接通道,接着客户端向服务器发送PORT命令和数据通道的端口BB,欲通过主动模式建立数据连接通道,而因为实际上连到FTP服务器的IP地址是经过NAT服务器进行转换的,故服务器实际上是连接到了NAT服务器的BB端口(此时NAT的BB端口没有启用,故连接被拒绝),并且并没有相应的条目可以找到客户端,所以此时的主动模式时不能成功的。
                                           
解决方式可以自己在NAT配置映射信息,允许FTP服务器连接过来。如果手工配置映射条目,那么就必须知道FTP服务器是哪一个端口发起连接过来,所以FTP的主动模式发起连接的端口规定为20端口而不是动态选择,否则NAT映射的信息会很多。

FTP客户端处于NAT或防火墙之后的被动模式


如果FTP客户端处于NAT或防火墙之后,并且使用被动连接,此时是可以连接成功的,示意图如下图所示,过程和之前的类似,这里不再重复。

                                               


FTP服务器处于NAT或防火墙之后的被动模式


如果FTP服务器处于NAT或防火墙之后,在建立控制连接通道的时候,由于是客户端向服务器发起连接,因此需要在NAT配置一个映射条目(FTP服务器固定是21端口),经过三次握手建立控制连接通道。若使用被动模式,则在建立数据连接通道的时候,处于外网的客户端向处于内网的服务器发起的连接可能建立不能成功,这个和之前的也是类似的。所以我们可以知道,当FTP服务器处于NAT或防火墙之后的被动模式可能建立不成功。

                                

FTP服务器处于NAT或防火墙之后的主动模式


 从上面的分析我们应该可以得到,FTP服务器处于NAT或防火墙之后的被动模式是可以建立成功的。如下图所示
                                        


FTP的进程模型


FTP服务器是采用多进程的方式实现的,而且每来一个连接,创建了两个进程来为这个连接服务。


为什么采用多进程


FTP服务器是绝对不能采用多线程的。假如现在我们使用的是多线程的方式,此时有三个用户(A,B,C)连接过来,则服务器创建了三个线程(A,B,C)来进行处理。此时,假设三个客户端登陆的是同一个用户LCW,并且A将目录切换到a,B将目录切换到b,C将目录切换到c,那么他们是会相互影响到的,因为多个线程是共享同一个工作目录的,当前线程对工作目录的修改回影响到其他的线程,这是不允许的,所以不能采用多线程的方式。同时IO复用也是不可以的(单线程,会影响其他连接)


为什么一个连接要用两个进程


那为什么一个客户端连接过来要采用两个进程呢?

这其实是出于一些安全性的考虑,一些权限方面的限制。假如此时有一个普通用户LCW连接过来,则当前进程会更改为LCW进程,而在要使用FTP的主动模式进行数据传输的时候,FTP要向客户端发起连接,FTP服务器需要绑定一个20端口,而LCW是一个普通的用户,没有权限进行端口的绑定,这就意味着他无法建立正常的数据通道。所以需要一个进程nobody进程,来协助LCW进程(服务进程)。还有在其他某些操作的时候,我们不希望客户端用拥有太大的权限,反正某些危险的操作,因此把需要特殊权限的操作都交由nobody进程来完成,而服务进程只是完成和客户端的通信。

LCW进程称为服务进程,主要是用来实现与客户端进行通信,而nobody进程为协助进程,主要协助LCW进程完成一些和特殊权限相关的操作,因而一个连接需要使用两个进程来服务。其进程模式如下图所示:

                                      




                                                                








posted @ 2016-03-12 23:41  sigma0  阅读(290)  评论(0编辑  收藏  举报