{C++系列} 中期项目 FTP客户端的实现
in C/C++ with 0 comment

{C++系列} 中期项目 FTP客户端的实现

in C/C++ with 0 comment

#ftp原理

#FTP 概述

文件传输协议(FTP)作为网络共享文件的传输协议,在网络应用软件中具有广泛的应用。FTP的目标是提高文件的共享性和可靠高效地传送数据。
在传输文件时,FTP 客户端程序先与服务器建立连接,然后向服务器发送命令。服务器收到命令后给予响应,并执行命令。FTP 协议与操作系统无关,任何操作系统上的程序只要符合 FTP 协议,就可以相互传输数据。本文主要基于 LINUX 平台,对 FTP 客户端的实现原理进行详尽的解释并阐述如何使用 C 语言编写一个简单的 FTP 客户端。

#FTP 协议

相比其他协议,如 HTTP 协议,FTP 协议要复杂一些。与一般的 C/S 应用不同点在于一般的C/S 应用程序一般只会建立一个 Socket 连接,这个连接同时处理服务器端和客户端的连接命令和数据传输。而FTP协议中将命令与数据分开传送的方法提高了效率。
FTP 使用 2 个端口,一个数据端口和一个命令端口(也叫做控制端口)。这两个端口一般是21 (命令端口)和 20 (数据端口)。控制 Socket 用来传送命令,数据 Socket 是用于传送数据。每一个 FTP 命令发送之后,FTP 服务器都会返回一个字符串,其中包括一个响应代码和一些说明信息。其中的返回码主要是用于判断命令是否被成功执行了。

#命令端口

一般来说,客户端有一个 Socket 用来连接 FTP 服务器的相关端口,它负责 FTP 命令的发送和接收返回的响应信息。一些操作如“登录”、“改变目录”、“删除文件”,依靠这个连接发送命令就可完成。

#数据端口

对于有数据传输的操作,主要是显示目录列表,上传、下载文件,我们需要依靠另一个 Socket来完成。

如果使用被动模式,通常服务器端会返回一个端口号。客户端需要用另开一个 Socket 来连接这个端口,然后我们可根据操作来发送命令,数据会通过新开的一个端口传输。

如果使用主动模式,通常客户端会发送一个端口号给服务器端,并在这个端口监听。服务器需要连接到客户端开启的这个数据端口,并进行数据的传输。
下面对 FTP 的主动模式和被动模式做一个简单的介绍。

#主动模式 (PORT)

主动模式下,客户端随机打开一个大于 1024 的端口向服务器的命令端口 P,即 21 端口,发起连接,同时开放N +1 端口监听,并向服务器发出 “port N+1” 命令,由服务器从它自己的数据端口 (20) 主动连接到客户端指定的数据端口 (N+1)。

FTP 的客户端只是告诉服务器自己的端口号,让服务器来连接客户端指定的端口。对于客户端的防火墙来说,这是从外部到内部的连接,可能会被阻塞。

#被动模式 (PASV)

为了解决服务器发起到客户的连接问题,有了另一种 FTP 连接方式,即被动方式。命令连接和数据连接都由客户端发起,这样就解决了从服务器到客户端的数据端口的连接被防火墙过滤的问题。

被动模式下,当开启一个 FTP 连接时,客户端打开两个任意的本地端口 (N > 1024 和 N+1) 。

第一个端口连接服务器的 21 端口,提交 PASV 命令。然后,服务器会开启一个任意的端口 (P > 1024 ),返回如“227 entering passive mode (127,0,0,1,4,18)”。 它返回了 227 开头的信息,在括号中有以逗号隔开的六个数字,前四个指服务器的地址,最后两个,将倒数第二个乘 256 再加上最后一个数字,这就是 FTP 服务器开放的用来进行数据传输的端口。如得到 227 entering passive mode (h1,h2,h3,h4,p1,p2),那么端口号是 p1*256+p2,ip 地址为h1.h2.h3.h4。这意味着在服务器上有一个端口被开放。客户端收到命令取得端口号之后, 会通过 N+1 号端口连接服务器的端口 P,然后在两个端口之间进行数据传输。

#主要用到的 FTP 命令

#FTP 响应码

客户端发送 FTP 命令后,服务器返回响应码。

响应码用三位数字编码表示:
第一个数字给出了命令状态的一般性指示,比如响应成功、失败或不完整。
第二个数字是响应类型的分类,如 2 代表跟连接有关的响应,3 代表用户认证。
第三个数字提供了更加详细的信息。

第一个数字的含义如下:

1 表示服务器正确接收信息,还未处理。
2 表示服务器已经正确处理信息。
3 表示服务器正确接收信息,正在处理。
4 表示信息暂时错误。
5 表示信息永久错误。

第二个数字的含义如下:

0 表示语法。
1 表示系统状态和信息。
2 表示连接状态。
3 表示与用户认证有关的信息。
4 表示未定义。
5 表示与文件系统有关的信息。

项目实现计划

需求分析

一,实现普通非加密ftp客户端,能实现一般情况下的各种ftp操作(如上)

ftp操作(登陆,上传文件,下载文件,覆盖文件(修改文件),文件重命名,退出登录)

1,尽量使用C++语言实现(兼容C)(多练C++特殊语法)

利用面向对象的思想

尽量实现软件分层

高内聚,低耦合(功能模块分层明显,不要互有纠缠)

使用继承。重载机制 http://blog.csdn.net/swartz_lubel/article/details/57115820(这种编写方式一定不可取)

http://blog.csdn.net/sun_wangdong/article/details/45868615(面向过程的方式,需要面向对象化)
http://blog.csdn.net/sjin_1314/article/details/42581515 (同上)

2,共有两个版本,版本一命令行界面,版本二Qt界面(仿filezila客户端(可自定义))

版本一:

功能分解:

    • 1,socket连接(能被继承)
    • 2,登录(主动模式,被动模式)(继承socket类)
      用户名 密码登录 匿名登录
  • 主动模式:

            二进制传输方式:
            ASCII传输方式:
    

    被动模式:

    版本二:

        
    基于版本一,实现GUI
        

    详细设计:

    计划将项目分为6各类,即每个类一个模块,暂时定义如下 预计命令行版最终代码量约为1500行上下
    (随着版本更迭修改,增加代码复用率,容错操作(try..catch),性能(单例模式使用))

    FtpClient类     包含ftp客户端各种信息,如连接本地端口号,远程端口号,命令格式的确定
    ClientSock类    核心类,能被其他类继承,是文件操作类的父类。支持ftp连接过程中的各种网络操作。(单例模式)
    FCommand类    定义且解析ftp操作中的各种命令,可与FtpString类结合。
    FileTrans类        文件传输类。(文件的上传和下载,断点续传)
    FAcount类          账户控制类        实现登录与退出 (登录时的主动模式与被动模式)
    FtpString类        负责字符串操作类,即对ftp操作中的各种命令,文件的解析,解析后的字符串(需要封装项目需要的强大的字符串操作函数)       

    编码要求

    例:
        class GetMyProjectName{}
    
    /*
    *作者信息:
    *创建时间:
    *功能:
    *
    */
    class FtpClient{
    Public:
        FtpClient();//默认构造函数
        FtpClient(arg1,);//重载构造函数1
        FtpClient(arg1,arg2=0)//重载构造函数2
        …
    Protected:
        //函数功能
        virtual Func1(){
            ...
        }
    private:
        string interval1;//这个变量代表的意义
        Int interval2;//这个变量代表的意义
    
    }
    
    Responses