b FTP简单介绍

–> go to 总目录

FTP 概述

控制连接端口21,数据传输端口20

文件传输协议(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 每个命令都有 3 到 4 个字母组成,命令后面跟参数,用空格分开。每个命令都以 "\r\n"结束。
要下载或上传一个文件,首先要登入 FTP 服务器,然后发送命令,最后退出。这个过程中,主要用到的命令有 USER、PASS、SIZE、REST、CWD、RETR、PASV、PORT、QUIT。

  • USER: 指定用户名。通常是控制连接后第一个发出的命令。“USER gaoleyi\r\n”: 用户名为gaoleyi 登录。
  • PASS: 指定用户密码。该命令紧跟 USER 命令后。“PASS gaoleyi\r\n”:密码为 gaoleyi。
  • SIZE: 从服务器上返回指定文件的大小。“SIZE file.txt\r\n”:如果 file.txt 文件存在,则返回该文件的大小。
  • CWD: 改变工作目录。如:“CWD dirname\r\n”。
  • PASV: 让服务器在数据端口监听,进入被动模式。如:“PASV\r\n”。
  • PORT: 告诉 FTP 服务器客户端监听的端口号,让 FTP 服务器采用主动模式连接客户端。如:“PORT h1,h2,h3,h4,p1,p2”。
  • RETR: 下载文件。“RETR file.txt \r\n”:下载文件 file.txt。
  • STOR: 上传文件。“STOR file.txt\r\n”:上传文件 file.txt。
  • REST: 该命令并不传送文件,而是略过指定点后的数据。此命令后应该跟其它要求文件传输的 FTP 命令。“REST 100\r\n”:重新指定文件传送的偏移量为 100 字节。
  • QUIT: 关闭与服务器的连接。

FTP 响应码

客户端发送 FTP 命令后,服务器返回响应码。
响应码用三位数字编码表示:
第一个数字给出了命令状态的一般性指示,比如响应成功、失败或不完整。
第二个数字是响应类型的分类,如 2 代表跟连接有关的响应,3 代表用户认证。
第三个数字提供了更加详细的信息。
第一个数字的含义如下:
1 表示服务器正确接收信息,还未处理。
2 表示服务器已经正确处理信息。
3 表示服务器正确接收信息,正在处理。
4 表示信息暂时错误。
5 表示信息永久错误。
第二个数字的含义如下:
0 表示语法。
1 表示系统状态和信息。
2 表示连接状态。
3 表示与用户认证有关的信息。
4 表示未定义。
5 表示与文件系统有关的信息。
Socket 编程的几个重要步骤
Socket 客户端编程主要步骤如下:

示例

源地址
图 1. 客户端连接到服务器端
在这里插入图片描述
清单 1. 客户端连接到 FTP 服务器,接收欢迎信息

图 2. 客户端登录 FTP 服务器
在这里插入图片描述
清单 2. 客户端发送用户名和密码,登入 FTP 服务器
/* 命令 ”USER username\r\n” */
sprintf(send_buf,“USER %s\r\n”,username);
/*客户端发送用户名到服务器端 /
write(control_sock, send_buf, strlen(send_buf));
/
客户端接收服务器的响应码和信息,正常为 ”331 User name okay, need password.” */
read(control_sock, read_buf, read_len);

/* 命令 ”PASS password\r\n” /
sprintf(send_buf,“PASS %s\r\n”,password);
/
客户端发送密码到服务器端 /
write(control_sock, send_buf, strlen(send_buf));
/
客户端接收服务器的响应码和信息,正常为 ”230 User logged in, proceed.” /
read(control_sock, read_buf, read_le

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的Python3实现FTP认证服务器的示例代码: ```python import hashlib import socket import os # 定义一个字典,存储已注册的用户信息,key为用户名,value为密码 users = {'user1': 'password1', 'user2': 'password2'} # 定义一个哈希函数,用于将明文密码加密为哈希值 def hash_password(password): return hashlib.sha256(password.encode()).hexdigest() # 定义一个函数,用于验证用户是否合法 def authenticate_user(username, password): if username not in users: return False return hash_password(password) == users[username] # 创建一个TCP监听socket,接收客户端连接 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_socket.bind(('0.0.0.0', 21)) server_socket.listen() print('FTP server started, listening on port 21...') while True: # 接收客户端连接 client_socket, client_address = server_socket.accept() print('New connection from', client_address) # 发送欢迎信息 client_socket.send(b'220 Welcome to FTP server\r\n') # 接收客户端发送的用户名和密码 username = '' password = '' while True: data = client_socket.recv(1024).decode() if not data: break print('Received:', data.strip()) if data.startswith('USER '): username = data[5:].strip() client_socket.send(b'331 Password required for ' + username.encode() + b'\r\n') elif data.startswith('PASS '): password = data[5:].strip() if authenticate_user(username, password): client_socket.send(b'230 Logged on\r\n') break else: client_socket.send(b'530 Login incorrect\r\n') # 如果用户验证通过,接收客户端发送的FTP命令 if username and password: client_socket.send(b'220 FTP server ready\r\n') while True: data = client_socket.recv(1024).decode() if not data: break print('Received:', data.strip()) if data.startswith('QUIT'): client_socket.send(b'221 Goodbye\r\n') break elif data.startswith('PWD'): current_dir = os.getcwd() client_socket.send(('257 "%s"\r\n' % current_dir).encode()) elif data.startswith('CWD '): path = data[4:].strip() try: os.chdir(path) client_socket.send(('250 CWD command successful\r\n').encode()) except FileNotFoundError: client_socket.send(('550 Directory not found\r\n').encode()) elif data.startswith('LIST'): file_list = os.listdir('.') response = ' '.join(file_list) + '\r\n' client_socket.send(('150 Opening data connection\r\n').encode()) data_socket, _ = server_socket.accept() data_socket.send(response.encode()) data_socket.close() client_socket.send(('226 Transfer complete\r\n').encode()) else: client_socket.send(('502 Command not implemented\r\n').encode()) # 关闭客户端socket client_socket.close() ``` 使用方法: 1. 将代码保存为ftp_server.py文件; 2. 在终端中运行命令python ftp_server.py,启动FTP服务器; 3. 使用FTP客户端连接到服务器,输入用户名和密码进行验证,然后执行FTP命令。 注意:此示例代码仅为演示使用,实际使用时应该加强安全性,例如使用SSL/TLS加密通信、限制IP地址访问、使用更强的密码哈希算法等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值