C# 开发一个简单的FTP Server

B站影视 内地电影 2025-06-09 13:07 2

摘要:在这篇文章中,我们将学习如何使用C#开发一个简单的FTP服务器。FTP(File Transfer Protocol)是一种用于在网络上的计算机之间传输文件的标准网络协议。C#提供了强大的网络编程功能,使得我们可以方便地创建自定义的FTP服务器。本文将引导你通

在这篇文章中,我们将学习如何使用C#开发一个简单的FTP服务器。FTP(File Transfer Protocol)是一种用于在网络上的计算机之间传输文件的标准网络协议。C#提供了强大的网络编程功能,使得我们可以方便地创建自定义的FTP服务器。本文将引导你通过从基础开始一步一步地构建一个简单的FTP服务器应用程序。

在开始编码之前,确保你的项目已经正确设置。新建一个C#控制台应用程序项目,并确保添加了必要的引用。

在你的程序顶部,需要引用一些必要的命名空间来实现网络通信和文件操作:

using System;using System.IO;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading;

创建一个FTPServer类以处理FTP服务器的所有逻辑。

using System;using System.Collections.Generic;using System.Linq;using System.Net.Sockets;using System.Net;using System.Text;using System.Threading.Tasks;using System.Net.Security;using System.Security.Authentication;using System.Security.Cryptography.X509Certificates;using System.Globalization;namespace AppFtpServer{class FtpServer{privateTcpListener _listener;private bool _isRunning;private string _rootDirectory;public FtpServer(string ip, int port, string rootDirectory){_listener = new TcpListener(IPAddress.Parse(ip), port);_rootDirectory = rootDirectory;}public async Task Start{_isRunning = true;_listener.Start;Console.WriteLine($"FTP Server started. Listening for connections on port {((IPEndPoint)_listener.LocalEndpoint).Port}...");while (_isRunning){TcpClient client = await _listener.AcceptTcpClientAsync;_ = HandleClientAsync(client);}}private async Task HandleClientAsync(TcpClient client){using (NetworkStream networkStream = client.GetStream)using (StreamReader reader = new StreamReader(networkStream))using (StreamWriter writer = new StreamWriter(networkStream) { AutoFlush = true }){await writer.WriteLineAsync("220 Welcome to Simple FTP Server");string username = null;bool isLoggedIn = false;string currentDirectory = _rootDirectory;TcpListener dataListener = null; // New field for managing the data connectionwhile (true){string command = await reader.ReadLineAsync;if (string.IsNullOrEmpty(command))break;string parts = command.Split(' ');string cmd = parts[0].ToUpper;switch (cmd){case "USER":username = parts[1];await writer.WriteLineAsync("331 User name okay, need password");break;case "PASS":if (username == "admin" && parts[1] == "password"){isLoggedIn = true;await writer.WriteLineAsync("230 User logged in");}else{await writer.WriteLineAsync("530 Login incorrect");}break;case "PWD":if (!isLoggedIn){await writer.WriteLineAsync("530 Not logged in");break;}string relativePath = GetRelativePath(_rootDirectory, currentDirectory);await writer.WriteLineAsync($"257 \"{relativePath}\" is current directory");break;case "CWD":if (!isLoggedIn){await writer.WriteLineAsync("530 Not logged in");break;}if (parts.Length

注意:关于目录文件的处理不同FTP客户端好像有些不同,我这用的是FileZilla做的测试,这中间还有中文乱码问题,需要修改一个连接中的配置。

USER 命令:客户端发送: USER [用户名] 服务器响应:如果用户名已发送: 331 User name okay, need password(用户名正确,需要密码)PASS 命令:客户端发送: PASS [密码] 服务器响应:如果用户名是"admin"且密码是"password": 230 User logged in(用户已登录) 如果凭证不匹配: 530 Login incorrect(登录不正确)PWD 命令:(打印工作目录) 客户端发送: PWD 服务器响应:如果未登录: 530 Not logged in(未登录) 如果已登录: 257 "[当前目录]" is current directory(当前目录)CWD 命令:(改变工作目录) 客户端发送: CWD [目录] 服务器响应:如果未登录:如果目录参数缺失: 501 Syntax error in parameters or arguments(参数或参数语法错误) 如果访问新目录被拒绝: 550 Requested action not taken. Access denied.(请求的操作未执行,访问被拒绝) 如果目录找到并可访问: 250 Directory successfully changed.(目录成功更改) 如果目录未找到: 550 Requested action not taken. Directory not found.(请求的操作未执行,未找到目录)RETR 命令:(检索文件) 客户端发送: RETR [文件] 服务器响应:如果未登录:如果文件参数缺失:如果文件访问被拒绝: 550 Requested action not taken. File access denied.(请求的操作未执行,文件访问被拒绝) 如果文件找到并开始传输: 150 Opening data connection for file transfer.(正在为文件传输打开数据连接) 文件传输成功完成后: 226 Transfer complete.(传输完成) 如果文件未找到: 550 File not found.(文件未找到)TYPE 命令:客户端发送: TYPE [类型] (在代码中,仅处理TYPE I,即二进制模式) 服务器响应: 200 Type set to I(类型设置为I)PASV 命令:(进入被动模式) 客户端发送: PASV 服务器响应: 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)(进入被动模式),其中h1,h2,h3,h4是IP地址,p1,p2是被动模式下的数据端口。LIST 命令:(列出目录) 客户端发送: LIST 服务器响应:在开始传输数据之前: 150 Here comes the directory listing.(这里是目录列表) 在目录列表成功发送后: 226 Directory send OK.(目录发送成功)STOR 命令:(存储文件) 客户端发送: STOR [文件] 服务器响应:如果未登录:如果文件参数缺失:如果文件存储被拒绝:在文件上传开始之前: 150 Opening data connection for file upload.(正在为文件上传打开数据连接) 文件上传成功完成后:QUIT 命令:(退出) 客户端发送: QUIT 服务器响应: 221 Goodbye(再见)未识别或未实现的命令:服务器响应: 502 Command not implemented(命令未实现)

在Main方法中实例化并启动你的FTP服务器:

public static async Task Main(string args){string ip = "127.0.0.1";int port = 21;string rootDirectory;if (args.Length > 0 && Directory.Exists(args[0])){rootDirectory = Path.GetFullPath(args[0]);}else{rootDirectory = "d:\\book";while (!Directory.Exists(rootDirectory)){Console.WriteLine("Directory does not exist. Please enter a valid path:");rootDirectory = Console.ReadLine;}rootDirectory = Path.GetFullPath(rootDirectory);}Console.WriteLine($"Using root directory: {rootDirectory}");FtpServer server = new FtpServer(ip, port, rootDirectory);await server.Start;}

本文介绍了如何用C#开发一个基本的FTP服务器。我们的服务器目前支持基本的FTP命令并且能够响应客户端的请求。虽然这是一个简化的版本,但它为更复杂和功能完整的FTP服务器打下了基础。可以尝试扩展这个服务器,支持更多的FTP命令,添加认证、加密、和更复杂的文件管理等高级功能。

来源:丫亚的乐园

相关推荐