实现 Linux FTP 服务器
概述
本项目旨在实现一个基于 RFC959 FTP 协议的 Linux FTP 服务器,支持基本的 FTP 操作,包括文件上传、下载、列出目录等功能。该服务器需要能够在被动模式(PASV)下正常工作。
知识要点
- Linux 系统编程
- 网络编程
- 多线程编程
- 并发编程
任务说明
FTP(文件传输协议)是 TCP/IP 协议族中的一种应用层协议,基于 TCP 传输。
通常情况下,FTP 使用 TCP 的 20 和 21 端口,其中 20 端口用于数据传输,21 端口用于控制信息传输。是否使用 20 端口传输数据取决于 FTP 的传输模式:
- 主动模式:数据传输使用 20 端口;
- 被动模式:数据传输端口由服务器和客户端协商决定。
本项目要求实现一个支持被动模式(PASV)的 FTP 服务器,支持基本的上传、下载、列出目录等功能,并使用 2100 端口作为控制连接端口。
任务流程
-------------
|/---------\|
|| User || --------
||Interface|<--->| User |
|\----^----/| --------
---------- | | |
|/------\| FTP Commands |/----V----\|
||Server|<---------------->| User ||
|| PI || FTP Replies || PI ||
|\--^---/| |\----^----/|
| | | | | |
-------- |/--V---\| Data |/----V----\| --------
| File |<--->|Server|<---------------->| User |<--->| File |
|System| || DTP || Connection || DTP || |System|
-------- |\------/| |\---------/| --------
---------- -------------
Server-FTP USER-FTP
- FTP 客户端通过一个随机端口N(通常大于1024)向 FTP 服务器的 2100 端口发起连接请求。
- FTP 服务器的主进程接收到请求后,创建一个服务端控制线程,与客户端控制线程建立控制连接,开始会话。
- 当 FTP 客户端需要传输数据文件时,客户端控制线程向服务端控制线程发送 PASV 命令。
-
服务端控制线程接收到 PASV 请求后,创建一个数据传输线程,并将生成的端口号告知客户端控制线程,返回 227 entering passive mode (h1,h2,h3,h4,p1,p2),其中端口号为 p1*256+p2,IP 地址为 h1.h2.h3.h4。
假设服务器的 IP 地址为 192.168.1.1,生成的端口号为 5000 那么返回的响应将是:227 entering passive mode (192,168,1,1,19,136) 其中 19 和 136 分别是 5000 的高位和低位字节(5000 = 19*256 + 136)
-
客户端控制线程收到响应后,创建一个客户端数据传输线程,随机选择一个客户端数据传输端口,连接到服务端的数据传输端口(即前述的 IP 和端口号),然后进行数据文件传输。
- 数据传输完成后,服务端数据传输进程通知传输结束,关闭数据连接通道,但保留控制连接通道。
- 如果没有其他文件需要传输,控制连接通道也将关闭。
客户端设计
- 连接服务器:通过控制连接连接到服务器的 2100 端口。
- 请求被动模式(PASV):发送 PASV 命令请求服务器提供用于数据传输的端口。
- 获取文件列表:通过控制连接发送 LIST 命令,并通过数据连接接收文件数据。
- 文件上传与下载:
- 上传:通过控制连接发送 STOR 命令,并使用数据连接上传文件。
- 下载:通过控制连接发送 RETR 命令,并使用数据连接下载文件。
- 完成文件传输后,客户端关闭数据连接。
服务器设计
- 监听客户端连接:监听 2100 端口,等待客户端建立控制连接。
- 处理被动模式请求:当客户端请求进入被动模式时,服务器生成一个随机端口用于数据传输。
- 文件传输:通过数据连接传输文件数据。
- 完成操作后,关闭本次数据连接。
提高要求(选做)
- 支持用户身份验证。
- 支持断点续传。
- 使用线程池优化服务器性能。
- 使用非阻塞 I/O 和 epoll 优化服务器性能。
- 优化大文件传输。
验收要求
- 实现 FTP 服务器的基本功能,支持被动模式(PASV)。
- 支持文件上传、下载、列出目录等功能。
- 支持提高要求中的部分或全部功能。
- 界面美观。
- 无资源与内存泄漏。
提交方式
- 在任务截止时间之前将代码上传到个人仓库。
- 截止时间: