C++的简单FTP客户端实现(一)FTP基础知识

FTP(File Transfer Protocol,文件传输协议) 是 TCP/IP 协议组中的协议之一。FTP协议包括两个组成部分,其一为FTP服务器,其二为FTP客户端。其中FTP服务器用来存储文件,用户可以使用FTP客户端通过FTP协议访问位于FTP服务器上的资源。在开发网站的时候,通常利用FTP协议把网页或程序传到Web服务器上。此外,由于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+p2ip 地址为h1.h2.h3.h4。这意味着在服务器上有一个端口被开放。客户端收到命令取得端口号之后, 会通过 N+1 号端口连接服务器的端口 P,然后在两个端口之间进行数据传输。

FTP命令及响应

客户端命令

服务端响应

另外还需要了解Socket的错误信息,在编程的时候会用到。

有了这些基础知识,如何在编程时使用,请见下一篇

C++的简单FTP客户端实现(二)编程

以及实际代码

QT C++实现的FTP客户端,带断点续传功能

  • 6
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FTP(File Transfer Protocol)是一种常用的文件传输协议,它允许用户在网络上通过 FTP 客户端FTP 服务器之间传输文件。 下面是一个简单的 C 实现 FTP 客户端的代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <unistd.h> #define BUF_SIZE 1024 int main(int argc, char *argv[]) { int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { perror("socket"); exit(1); } struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(21); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("connect"); exit(1); } char buffer[BUF_SIZE]; int recv_len; recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); char user[] = "USER anonymous\r\n"; if (send(sock, user, strlen(user), 0) == -1) { perror("send"); exit(1); } recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); char pass[] = "PASS anonymous\r\n"; if (send(sock, pass, strlen(pass), 0) == -1) { perror("send"); exit(1); } recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); char pwd[] = "PWD\r\n"; if (send(sock, pwd, strlen(pwd), 0) == -1) { perror("send"); exit(1); } recv_len = recv(sock, buffer, BUF_SIZE-1, 0); if (recv_len == -1) { perror("recv"); exit(1); } buffer[recv_len] = '\0'; printf("%s", buffer); close(sock); return 0; } ``` 这段代码实现FTP 客户端的基本功能,包括连接 FTP 服务器、登录、获取当前目录等。具体来说,它的实现步骤如下: 1. 创建一个 TCP 套接字; 2. 设置 FTP 服务器的地址和端口号; 3. 连接 FTP 服务器; 4. 接收 FTP 服务器的欢迎信息; 5. 发送用户名和密码,进行登录; 6. 接收登录成功信息; 7. 发送命令 PWD,获取当前目录; 8. 接收当前目录信息; 9. 关闭套接字。 在实际应用中,我们可以根据需要扩展这段代码,实现更多 FTP 客户端的功能,比如上传、下载、删除等。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值