几个月前按照网上的教程写了一个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进程完成一些和特殊权限相关的操作,因而一个连接需要使用两个进程来服务。其进程模式如下图所示:

FTP服务器项目的一些整理的更多相关文章

  1. 【项目】手写FTP服务器-C++实现FTP服务器

    X_FTP_server 手写FTP服务器-C++实现FTP服务器 项目Gitee链接:https://gitee.com/hsby/ftp_Server 简介 一个基于libevent的高并发FTP ...

  2. 在windwo server2008服务器上配置ftp服务器、及配置phpstrom工具、实现项目同步。

    在windwo server2008服务器上配置ftp服务器.及配置phpstrom工具.实现项目同步. 在windwo server2008服务器上配置ftp服务器 参考该篇文章:http://bl ...

  3. 【VS2019】Web项目发布时提示无法连接FTP服务器

    使用 Visual Studio 2019 时出现的问题 环境:win10 ltsc 场景 发布Web项目到FTP时 失败,并提示 _无法打开网站"ftp://...".未安装与 ...

  4. C#对.CSV格式的文件--逗号分隔值文件 的读写操作及上传ftp服务器操作方法总结

    前言 公司最近开发需要将数据保存到.csv文件(逗号分隔值 文件)中然后上传到ftp服务器上,供我们系统还有客户系统调用,之前完全没有接触过这个,所以先来看看百度的解释:逗号分隔值(Comma-Sep ...

  5. 免费ftp服务器FileZilla Server配置

    FileZilla Server下载安装完成后,必须启动软件进行设置,由于此软件是英文,本来就是一款陌生的软件,再加上英文,配置难度可想而知,小编从网上找到一篇非常详细的教程进行整理了一番,确保读到这 ...

  6. 使用SAXReader读取ftp服务器上的xml文件(原创)

    根据项目需求,需要监测ftp服务器上的文件变化情况,并将新添加的文件读入项目系统(不需要下载). spring配置定时任务就不多说了,需要注意的一点就是,现在的项目很多都是通过maven构建的,分好多 ...

  7. win7下如何建立ftp服务器

    前段时间正在做一个项目,需要上传东西到ftp服务器,纠结于如何建立ftp服务器.经过一番摸索.终于成功建立ftp服务器.现将我的经验跟大家分享一下.不足之处还望多多指点! 步骤/方法 首先在本地机器上 ...

  8. Pureftp-安全的ftp服务器部署

    一.简介: Pure-FTPd 是一款免费(BSD)的,安全的,高质量和符合标准的FTP服务器. 侧重于运行效率和易用性. 它提供了简单的答案,他满足了大众化的需求,包括普通用户以及主机供应商们 Pu ...

  9. centos架设FTP服务器

    1.安装vsftp在这里,我们架设的是虚拟用户,所谓虚拟用户就是没有使用真实的帐户,只是通过某种手段达到映射帐户和设置权限的目的.yum -y install vsftpd在CentOS中,这样就可以 ...

随机推荐

  1. android29之UI控件的抽屉式实现方法之一(DrawerLayout和NavigationView)

    添加依赖 implementation 'com.google.android.material:material:1.2.0-alpha06' 在Layout中创建两个Xml布局文件,header. ...

  2. Pytorch自定义创建BP神经网络

    class BPNet(nn.Module): def __init__(self, in_dim, n_hidden_1, n_hidden_2,\ n_hidden_3, n_hidden_4, ...

  3. spark——详解rdd常用的转化和行动操作

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是spark第三篇文章,我们继续来看RDD的一些操作. 我们前文说道在spark当中RDD的操作可以分为两种,一种是转化操作(trans ...

  4. Camunda 流程引擎的一种 Adapter 层实现

    上一篇说明了选择 Camunda 的理由.这一篇说明如何实现适配层. 当前还没有专门写一篇对 Camunda 各个功能的详细介绍.如果要获得比较直观的感受,可以下载 Modeler 或者使用在线版的 ...

  5. GeiGebra指令

  6. 在众多小说中,Python告诉你哪本小说好看

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 有趣的Python PS:如有需要Python学习资料的小伙伴可以 ...

  7. docker 概览 (1)

    Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化.容器是完全使 ...

  8. 3. string

    let str = "my string"; 1. str.startsWith('my'); //true2.str.endsWith('my'); //false3.str.i ...

  9. 纯css画三角形

    纯css画三角形与border元素相关 设置border的属性 width: 100px; height: 100px; border-style: solid; border-width: 100p ...

  10. 解决sublime打开文档,出现中文乱码问题

    sublime text 软件中出现中文乱码,大多是因为编码格式不支持,需要安装一个插件就可以解决中文乱码问题,推荐安装 ConvertToUtf8  安装步骤: 1.按“shift + ctrl + ...