FTP客户端C 版
JAVA中的FtpClient与FTPClient,并实现jsp页面下载ftp服务器上的文件
JAVA中的FtpClient与FTPClient,并实现jsp页面下载ftp服务器上的文件这段时间一直在研究Java如何访问Ftp,搞了一段时间了,也有一定的了解。
故此记录一下。
ftp和FTP我个人觉得FTP更符合我们程序员的口味,不管是方法命名还是API的详细与否,或者是开发平台的问题,FTP毕竟是Apache的东西,做的就是不错。
其实web开发中一般都会涉及到编码问题,所以web上传下载一定会有中文乱码的问题存在,而FTP对中文的支持比ftp要好多了。
使用ftpClient不需要导入其它jar包,只要你使用java语言开发就行了,而使用FTPClient 需要使用commons-net-1.4.1.jar和jakarta-oro-2.0.8.jar,当然jar版本随便你自己。
话不多说,上代码!FTP服务器的文件目录结构图:一、FtpClientFtpClient是属于JDK的包下面的类,但是jdkapi并没有对此作介绍,在中文支持上面也有一定的限制。
本段代码中的Ftp服务器的IP地址,用户名和密码均通过SystemConfig.properties文档获取Ftp_client.java[java]view plain copy1.package com.iodn.util;2.3.import java.io.ByteArrayOutputStream;4.import java.io.File;5.import java.io.FileInputStream;6.import java.io.FileOutputStream;7.import java.io.IOException;8.import java.util.ResourceBundle;9.import .TelnetInputStream;10.import .TelnetOutputStream;11.import .ftp.FtpClient;12.13.public class Ftp_client {14.15.//FTP客户端16.private FtpClient ftpClient;17.private ResourceBundle res=null;18./**19. * 连接FTP服务器20. * @param path 指定远程服务器上的路径21. */22.public Ftp_client(String path){23.24. res = ResourceBundle.getBundle("com.iodn.util.SystemConfig");//获取配置文件propeties文档中的数据25.try{26. ftpClient=new FtpClient(res.getString("Properties.ftpHostIp"));//如果不想使用配置文件即可将数据写死(如:192.168.1.10)27. ftpClient.login(res.getString("Properties.ftpUser"), res.getString("Properties.ftpPassword"));//Ftp服务器用户名和密码28. ftpClient.binary();29. System.out.println("Login Success!");30.if(path.length()!=0){31.//把远程系统上的目录切换到参数path所指定的目录(可不用设置,上传下载删除时加Ftp中的全路径即可)32. ftpClient.cd(path);33. }34. }catch(Exception e){35. e.printStackTrace();36. }37. }38.39./**40. * 上传文件41. * @param remoteFile42. * @param localFile43. */44.public boolean upload(String remoteFile, String localFile){45.boolean bool=false;46. TelnetOutputStream os=null;47. FileInputStream is=null;48.try{49. os=ftpClient.put(remoteFile);50. is=new FileInputStream(new File(localFile));51.byte[] b=new byte[1024];52.int c;53.while((c=is.read(b))!=-1){54. os.write(b, 0, c);55. }56. bool=true;57. }catch(Exception e){58. e.printStackTrace();59. System.out.println("上传文件失败!请检查系统FTP设置,并确认FTP服务启动");60. }finally{61.if(is!=null){62.try {63. is.close();64. } catch (IOException e) {65. e.printStackTrace();66. }67. }68.if(os!=null){69.try {70. os.close();71. } catch (IOException e) {72. e.printStackTrace();74. }75. closeConnect();76. }77.return bool;78. }79./**80. * 下载文件81. * @param remoteFile 远程文件路径(服务器端)82. * @param localFile 本地文件路径(客户端)83. */84.85.public void download(String remoteFile, String localFile) {86. TelnetInputStream is=null;87. FileOutputStream os=null;88.try{89.//获取远程机器上的文件filename,借助TelnetInputStream把该文件传送到本地。
C语言实现FTP服务器
C语⾔实现FTP服务器公共部分代码/*common.h*/#ifndef COMMON_H#define COMMON_H#include <arpa/inet.h>#include <ctype.h>#include <dirent.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <netinet/in.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/wait.h>#include <sys/socket.h>#include <sys/types.h>#include <unistd.h>#define DEBUG 1#define MAXSIZE 512#define CLIENT_PORT_ID 30020struct command{char arg[255];char code[5];};int socket_create(int port);int socket_accept(int sock_listen);int socket_connect(int port, char *host);int recv_data(int sockfd, char* buf, int bufsize);int send_response(int sockfd, int rc);void trimstr(char *str, int n);void read_input(char* buffer, int size);#endif/*common.c*/#include "common.h"/*** 创建监听套接字* 错误返回 -1,正确返回套接字描述符*/int socket_create(int port){int sockfd;int yes = 1;struct sockaddr_in sock_addr;// 创建套接字if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("socket() error");return -1;}// 设置本地套接字地址sock_addr.sin_family = AF_INET;sock_addr.sin_port = htons(port);sock_addr.sin_addr.s_addr = htonl(INADDR_ANY);if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {close(sockfd);perror("setsockopt() error");return -1;}// 绑定本地套接字地址到套接字if (bind(sockfd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) < 0){close(sockfd);perror("bind() error");return -1;}// 将套接字设置为监听状态if (listen(sockfd, 5) < 0){close(sockfd);perror("listen() error");return -1;}return sockfd;}/*** 套接字接受请求* 错误返回 -1,正确返回新的连接套接字*/int socket_accept(int sock_listen){int sockfd;struct sockaddr_in client_addr;socklen_t len = sizeof(client_addr);sockfd = accept(sock_listen, (struct sockaddr *) &client_addr, &len); // 等待连接if (sockfd < 0){perror("accept() error");return -1;}return sockfd;}/*** 连接远端主机* 成功返回套接字描述符,失败返回 -1*/int socket_connect(int port, char*host){int sockfd;struct sockaddr_in dest_addr;/* 创建套接字 */if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){perror("error creating socket");return -1;}/* 设置协议地址 */memset(&dest_addr, 0, sizeof(dest_addr));dest_addr.sin_family = AF_INET;dest_addr.sin_port = htons(port);dest_addr.sin_addr.s_addr = inet_addr(host);/* 在套接字上创建连接 */if(connect(sockfd, (struct sockaddr *)&dest_addr, sizeof(dest_addr)) < 0 ){perror("error connecting to server");return -1;}return sockfd;}/*** 接收数据* 错误返回 -1,正确返回接收的字节数*/int recv_data(int sockfd, char* buf, int bufsize){size_t num_bytes;memset(buf, 0, bufsize);/* 调⽤ recv 函数读取套接字数据 */num_bytes = recv(sockfd, buf, bufsize, 0);if (num_bytes < 0)return -1;return num_bytes;}/*** 去除字符串中的空格和换⾏符*/void trimstr(char *str, int n){int i;for (i = 0; i < n; i++){if (isspace(str[i])) str[i] = 0;if (str[i] == '\n') str[i] = 0;}}/*** 发送响应码到 sockfd* 错误返回 -1,正确返回 0*/int send_response(int sockfd, int rc){int conv = htonl(rc);if (send(sockfd, &conv, sizeof conv, 0) < 0 ){perror("error sending...\n");return -1;}return0;}/*** 从命令⾏中读取输⼊*/void read_input(char* buffer, int size){char *nl = NULL;memset(buffer, 0, size);if ( fgets(buffer, size, stdin) != NULL ){nl = strchr(buffer, '\n');if (nl)*nl = '\0'; // 出现换⾏符,则将该位置部位'\0'(字符串结尾)}}客户端代码:/*ftclient.h*/#ifndef FTCLIENT_H#define FTCLIENT_H#include "../common/common.h"int read_reply();void print_reply(int rc);int ftclient_read_command(char* buf, int size, struct command *cstruct); int ftclient_get(int data_sock, int sock_control, char* arg);int ftclient_open_conn(int sock_con);int ftclient_list(int sock_data, int sock_con);int ftclient_send_cmd(struct command *cmd);void ftclient_login();#endifftclient.c*/#include "ftclient.h"int sock_control;/*** 接收服务器响应* 错误返回 -1,正确返回状态码*/int read_reply(){int retcode = 0;if (recv(sock_control, &retcode, sizeof retcode, 0) < 0){perror("client: error reading message from server\n");return -1;}return ntohl(retcode);}/*** 打印响应信息*/void print_reply(int rc){switch (rc){case220:printf("220 Welcome, server ready.\n");break;case221:printf("221 Goodbye!\n");break;case226:printf("226 Closing data connection. Requested file action successful.\n");break;case550:printf("550 Requested action not taken. File unavailable.\n");break;}}/*** 解析命令⾏到结构体*/int ftclient_read_command(char* buf, int size, struct command *cstruct){memset(cstruct->code, 0, sizeof(cstruct->code));memset(cstruct->arg, 0, sizeof(cstruct->arg));printf("ftclient> "); // 输⼊提⽰符fflush(stdout);read_input(buf, size); // 等待⽤户输⼊命令char *arg = NULL;arg = strtok (buf,"");arg = strtok (NULL, "");if (arg != NULL)strncpy(cstruct->arg, arg, strlen(arg));if (strcmp(buf, "list") == 0)strcpy(cstruct->code, "LIST");else if (strcmp(buf, "get") == 0)strcpy(cstruct->code, "RETR");else if (strcmp(buf, "quit") == 0)strcpy(cstruct->code, "QUIT");elsereturn -1; // 不合法memset(buf, 0, 400);strcpy(buf, cstruct->code); // 存储命令到 buf 开始处/* 如果命令带有参数,追加到 buf */if (arg != NULL){strcat(buf, "");strncat(buf, cstruct->arg, strlen(cstruct->arg));}return0;/*** 实现 get <filename> 命令⾏*/int ftclient_get(int data_sock, int sock_control, char* arg){char data[MAXSIZE];int size;FILE* fd = fopen(arg, "w"); // 创建并打开名字为 arg 的⽂件/* 将服务器传来的数据(⽂件内容)写⼊本地建⽴的⽂件 */ while ((size = recv(data_sock, data, MAXSIZE, 0)) > 0)fwrite(data, 1, size, fd);if (size < 0)perror("error\n");fclose(fd);return0;}/*** 打开数据连接*/int ftclient_open_conn(int sock_con){int sock_listen = socket_create(CLIENT_PORT_ID);/* 在控制连接上发起⼀个 ACK 确认 */int ack = 1;if ((send(sock_con, (char*) &ack, sizeof(ack), 0)) < 0){printf("client: ack write error :%d\n", errno);exit(1);}int sock_conn = socket_accept(sock_listen);close(sock_listen);return sock_conn;}/*** 实现 list 命令*/int ftclient_list(int sock_data, int sock_con){size_t num_recvd;char buf[MAXSIZE];int tmp = 0;/* 等待服务器启动的信息 */if (recv(sock_con, &tmp, sizeof tmp, 0) < 0){perror("client: error reading message from server\n");return -1;}memset(buf, 0, sizeof(buf));/* 接收服务器传来的数据 */while ((num_recvd = recv(sock_data, buf, MAXSIZE, 0)) > 0) {printf("%s", buf);memset(buf, 0, sizeof(buf));}if (num_recvd < 0)perror("error");/* 等待服务器完成的消息 */if (recv(sock_con, &tmp, sizeof tmp, 0) < 0){perror("client: error reading message from server\n");return -1;}return0;}/*** 输⼊含有命令(code)和参数(arg)的 command(cmd) 结构* 连接 code + arg,并放进⼀个字符串,然后发送给服务器*/int ftclient_send_cmd(struct command *cmd)char buffer[MAXSIZE];int rc;sprintf(buffer, "%s %s", cmd->code, cmd->arg);/* 发送命令字符串到服务器 */rc = send(sock_control, buffer, (int)strlen(buffer), 0); if (rc < 0){perror("Error sending command to server");return -1;}return0;}/*** 获取登录信息* 发送到服务器认证*/void ftclient_login(){struct command cmd;char user[256];memset(user, 0, 256);/* 获取⽤户名 */printf("Name: ");fflush(stdout);read_input(user, 256);/* 发送⽤户名到服务器 */strcpy(cmd.code, "USER");strcpy(cmd.arg, user);ftclient_send_cmd(&cmd);/* 等待应答码 331 */int wait;recv(sock_control, &wait, sizeof wait, 0);/* 获得密码 */fflush(stdout);char *pass = getpass("Password: ");/* 发送密码到服务器 */strcpy(cmd.code, "PASS");strcpy(cmd.arg, pass);ftclient_send_cmd(&cmd);/* 等待响应 */int retcode = read_reply();switch (retcode){case430:printf("Invalid username/password.\n");exit(0);case230:printf("Successful login.\n");break;default:perror("error reading message from server");exit(1);break;}}/* 主函数⼊⼝ */int main(int argc, char* argv[]){int data_sock, retcode, s;char buffer[MAXSIZE];struct command cmd;struct addrinfo hints, *res, *rp;/* 命令⾏参数合法性检测 */if (argc != 3){printf("usage: ./ftclient hostname port\n");exit(0);}char *host = argv[1]; //所要连接的服务器主机名char *port = argv[2]; //所要链接到服务器程序端⼝号/* 获得和服务器名匹配的地址 */memset(&hints, 0, sizeof(struct addrinfo));hints.ai_family = AF_UNSPEC;hints.ai_socktype = SOCK_STREAM;s = getaddrinfo(host, port, &hints, &res);if (s != 0){printf("getaddrinfo() error %s", gai_strerror(s));exit(1);}/* 找到对应的服务器地址并连接 */for (rp = res; rp != NULL; rp = rp->ai_next){sock_control = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); // 创建控制套接字if (sock_control < 0)continue;if(connect(sock_control, res->ai_addr, res->ai_addrlen)==0) // 和服务器连接break;else{perror("connecting stream socket");exit(1);}close(sock_control);}freeaddrinfo(rp);/* 连接成功,打印信息 */printf("Connected to %s.\n", host);print_reply(read_reply());/* 获取⽤户的名字和密码 */ftclient_login();while (1){ // 循环,直到⽤户输⼊ quit/* 得到⽤户输⼊的命令 */if ( ftclient_read_command(buffer, sizeof buffer, &cmd) < 0){printf("Invalid command\n");continue; // 跳过本次循环,处理下⼀个命令}/* 发送命令到服务器 */if (send(sock_control, buffer, (int)strlen(buffer), 0) < 0 ){close(sock_control);exit(1);}retcode = read_reply(); //读取服务器响应(服务器是否可以⽀持该命令?)if (retcode == 221) // 退出命令{print_reply(221);break;}if (retcode == 502)printf("%d Invalid command.\n", retcode);// 不合法的输⼊,显⽰错误信息else{// 命令合法 (RC = 200),处理命令/* 打开数据连接 */if ((data_sock = ftclient_open_conn(sock_control)) < 0){perror("Error opening socket for data connection");exit(1);}/* 执⾏命令 */if (strcmp(cmd.code, "LIST") == 0)ftclient_list(data_sock, sock_control);else if (strcmp(cmd.code, "RETR") == 0){if (read_reply() == 550) // 等待回复{print_reply(550);close(data_sock);continue;}ftclient_get(data_sock, sock_control, cmd.arg);print_reply(read_reply());}close(data_sock);}} // 循环得到更多的⽤户输⼊close(sock_control); // 关闭套接字控制连接return0;}makefile⽂件CC := gccCFLAGS := -Wall -g -OsSHDIR := ../commonOBJS = ftclient.o $(SHDIR)/common.oall: ftclientftclient: $(OBJS)@$(CC) -o ftclient $(CFLAGS) $(OBJS)$(OBJS) : %.o: %.c@$(CC) -c $(CFLAGS) $< -o $@.PHONY:clean:@rm -f *.o ftclient@rm -f ../common/*.o@echo Done cleaning服务端代码:/*ftserve.h*/#ifndef FTSERVE_H#define FTSERVE_H#include "../common/common.h"void ftserve_retr(int sock_control, int sock_data, char* filename); int ftserve_list(int sock_data, int sock_control);int ftserve_start_data_conn(int sock_control);int ftserve_check_user(char*user, char*pass);int ftserve_login(int sock_control);int ftserve_recv_cmd(int sock_control, char*cmd, char*arg); void ftserve_process(int sock_control);#endif/*ftserve.c*/#include "ftserve.h"/* 主函数⼊⼝ */int main(int argc, char *argv[])int sock_listen, sock_control, port, pid;/* 命令⾏合法性检测 */if (argc != 2){printf("usage: ./ftserve port\n");exit(0);}/* 将命令⾏传进来的服务器端⼝号(字符串)转换为整数 */port = atoi(argv[1]);/* 创建监听套接字 */if ((sock_listen = socket_create(port)) < 0 ){perror("Error creating socket");exit(1);}/* 循环接受不同的客户机请求 */while(1){/* 监听套接字接受连接请求,得到控制套接字,⽤于传递控制信息 */if ((sock_control = socket_accept(sock_listen)) < 0 )break;/* 创建⼦进程处理⽤户请求 */if ((pid = fork()) < 0)perror("Error forking child process");/* ⼦进程调⽤ ftserve_process 函数与客户端交互 */else if (pid == 0){close(sock_listen); // ⼦进程关闭⽗进程的监听套接字ftserve_process(sock_control);close(sock_control); //⽤户请求处理完毕,关闭该套接字exit(0);}close(sock_control); // ⽗进程关闭⼦进程的控制套接字}close(sock_listen);return0;}/*** 通过数据套接字发送特定的⽂件* 控制信息交互通过控制套接字* 处理⽆效的或者不存在的⽂件名*/void ftserve_retr(int sock_control, int sock_data, char* filename){FILE* fd = NULL;char data[MAXSIZE];size_t num_read;fd = fopen(filename, "r"); // 打开⽂件if (!fd)send_response(sock_control, 550); // 发送错误码 (550 Requested action not taken)else{send_response(sock_control, 150); // 发送 okay (150 File status okay)do{num_read = fread(data, 1, MAXSIZE, fd); // 读⽂件内容if (num_read < 0)printf("error in fread()\n");if (send(sock_data, data, num_read, 0) < 0) // 发送数据(⽂件内容)perror("error sending file\n");}while (num_read > 0);send_response(sock_control, 226); // 发送消息:226: closing conn, file transfer successful fclose(fd);}}* 响应请求:发送当前所在⽬录的⽬录项列表* 关闭数据连接* 错误返回 -1,正确返回 0*/int ftserve_list(int sock_data, int sock_control){char data[MAXSIZE];size_t num_read;FILE* fd;int rs = system("ls -l | tail -n+2 > tmp.txt"); //利⽤系统调⽤函数 system 执⾏命令,并重定向到 tmp.txt ⽂件if ( rs < 0){exit(1);}fd = fopen("tmp.txt", "r");if (!fd)exit(1);/* 定位到⽂件的开始处 */fseek(fd, SEEK_SET, 0);send_response(sock_control, 1);memset(data, 0, MAXSIZE);/* 通过数据连接,发送tmp.txt ⽂件的内容 */while ((num_read = fread(data, 1, MAXSIZE, fd)) > 0){if (send(sock_data, data, num_read, 0) < 0)perror("err");memset(data, 0, MAXSIZE);}fclose(fd);send_response(sock_control, 226); // 发送应答码 226(关闭数据连接,请求的⽂件操作成功)return0;}/*** 创建到客户机的⼀条数据连接* 成功返回数据连接的套接字* 失败返回 -1*/int ftserve_start_data_conn(int sock_control){char buf[1024];int wait, sock_data;if (recv(sock_control, &wait, sizeof wait, 0) < 0 ){perror("Error while waiting");return -1;}struct sockaddr_in client_addr;socklen_t len = sizeof client_addr;getpeername(sock_control, (struct sockaddr*)&client_addr, &len); // 获得与控制套接字关联的外部地址(客户端地址) inet_ntop(AF_INET, &client_addr.sin_addr, buf, sizeof(buf));/* 创建到客户机的数据连接 */if ((sock_data = socket_connect(CLIENT_PORT_ID, buf)) < 0)return -1;return sock_data;}/*** ⽤户资格认证* 认证成功返回 1,否则返回 0*/int ftserve_check_user(char*user, char*pass){char username[MAXSIZE];char password[MAXSIZE];char *pch;char buf[MAXSIZE];char *line = NULL;size_t num_read;size_t len = 0;FILE* fd;int auth = 0;fd = fopen(".auth", "r"); //打开认证⽂件(记录⽤户名和密码)if (fd == NULL){perror("file not found");exit(1);}/* 读取".auth" ⽂件中的⽤户名和密码,验证⽤户⾝份的合法性 */ while ((num_read = getline(&line, &len, fd)) != -1){memset(buf, 0, MAXSIZE);strcpy(buf, line);pch = strtok (buf,"");strcpy(username, pch);if (pch != NULL){pch = strtok (NULL, "");strcpy(password, pch);}/* 去除字符串中的空格和换⾏符 */trimstr(password, (int)strlen(password));if ((strcmp(user,username)==0) && (strcmp(pass,password)==0)) {auth = 1; // 匹配成功,标志变量 auth = 1,并返回break;}}free(line);fclose(fd);return auth;}/* ⽤户登录*/int ftserve_login(int sock_control){char buf[MAXSIZE];char user[MAXSIZE];char pass[MAXSIZE];memset(user, 0, MAXSIZE);memset(pass, 0, MAXSIZE);memset(buf, 0, MAXSIZE);/* 获得客户端传来的⽤户名 */if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1){perror("recv error\n");exit(1);}int i = 5;int n = 0;while (buf[i] != 0) //buf[0-4]="USER"user[n++] = buf[i++];/* ⽤户名正确,通知⽤户输⼊密码 */send_response(sock_control, 331);/* 获得客户端传来的密码 */memset(buf, 0, MAXSIZE);if ( (recv_data(sock_control, buf, sizeof(buf)) ) == -1){perror("recv error\n");exit(1);}i = 5;n = 0;while (buf[i] != 0) // buf[0 - 4] = "PASS"pass[n++] = buf[i++];return (ftserve_check_user(user, pass)); // ⽤户名和密码验证,并返回}/* 接收客户端的命令并响应,返回响应码 */int ftserve_recv_cmd(int sock_control, char*cmd, char*arg){int rc = 200;char buffer[MAXSIZE];memset(buffer, 0, MAXSIZE);memset(cmd, 0, 5);memset(arg, 0, MAXSIZE);/* 接受客户端的命令 */if ((recv_data(sock_control, buffer, sizeof(buffer)) ) == -1){perror("recv error\n");return -1;}/* 解析出⽤户的命令和参数 */strncpy(cmd, buffer, 4);char *tmp = buffer + 5;strcpy(arg, tmp);if (strcmp(cmd, "QUIT")==0)rc = 221;else if ((strcmp(cmd, "USER") == 0) || (strcmp(cmd, "PASS") == 0) || (strcmp(cmd, "LIST") == 0) || (strcmp(cmd, "RETR") == 0))rc = 200;elserc = 502; // ⽆效的命令send_response(sock_control, rc);return rc;}/* 处理客户端请求 */void ftserve_process(int sock_control){int sock_data;char cmd[5];char arg[MAXSIZE];send_response(sock_control, 220); // 发送欢迎应答码/* ⽤户认证 */if (ftserve_login(sock_control) == 1) // 认证成功send_response(sock_control, 230);else{send_response(sock_control, 430); // 认证失败exit(0);}/* 处理⽤户的请求 */while (1){/* 接收命令,并解析,获得命令和参数 */int rc = ftserve_recv_cmd(sock_control, cmd, arg);if ((rc < 0) || (rc == 221)) // ⽤户输⼊命令 "QUIT"break;if (rc == 200 ){/* 创建和客户端的数据连接 */if ((sock_data = ftserve_start_data_conn(sock_control)) < 0){close(sock_control);exit(1);}/* 执⾏指令 */if (strcmp(cmd, "LIST")==0)ftserve_list(sock_data, sock_control);else if (strcmp(cmd, "RETR")==0)ftserve_retr(sock_control, sock_data, arg);close(sock_data);// 关闭连接}}}⾥⾯还有⼀个保存密码账户⽂件.auth,这⾥就不列出。
FTP服务2种工作方式详解,PORT方式和PASV方式,(即主动模式和被动模式)
2种模式都是从服务器角度出发的,主动就是服务器主动连接客户机,被动就是服务器做监听,等客户机来连接PORT主动模式:命令发送后是由client建立N+1端口监听,然后让Server的N-1端口(默认为20)来连接这个端口,所以client需要开放1024以上端口。
Flashfxp可以指定port端口范围,方便设置防火墙PASV被动模式:命令发送后是由server建立1024以上端口监听(serv-u可以指定PASV监听端口范围),client用1024以上端口来连接。
整个过程server没有用到20(N-1)端口一、ftp的port和pasv模式的工作方式FTP使用2个TCP端口,首先是建立一个命令端口(控制端口),然后再产生一个数据端口。
国内很多教科书都讲ftp 使用21命令端口和20数据端口,这个应该是教书更新太慢的原因吧。
实际上FTP分为主动模式和被动模式两种,ftp工作在主动模式使用tcp 21和20两个端口,而工作在被动模式会工作在大于1024随机端口。
FTP最权威的参考见RFC 959,有兴趣的朋友可以仔细阅读ftp:///documents/rfc/rfc0959.txt的文档了解FTP详细工作模式和命令。
目前主流的FTP Server服务器模式都是同时支持port和pasv两种方式,但是为了方便管理安全管理防火墙和设置ACL了解FTP Server的port和pasv模式是很有必要的。
1.1 ftp port模式(主动模式)主动方式的FTP是这样的:客户端从一个任意的非特权端口N(N>1024)连接到FTP服务器的命令端口(即tcp 21端口)。
紧接着客户端开始监听端口N+1,并发送FTP命令“port N+1”到FTP服务器。
最后服务器会从它自己的数据端口(20)连接到客户端指定的数据端口(N+1),这样客户端就可以和ftp服务器建立数据传输通道了。
ftp port模式工作流程如下图所示:针对FTP服务器前面的防火墙来说,必须允许以下通讯才能支持主动方式FTP:1、客户端口>1024端口到FTP服务器的21端口(入:客户端初始化的连接S<-C)2、FTP服务器的21端口到客户端>1024的端口(出:服务器响应客户端的控制端口S->C)3、FTP服务器的20端口到客户端>1024的端口(出:服务器端初始化数据连接到客户端的数据端口S->C)4、客户端>1024端口到FTP服务器的20端口(入:客户端发送ACK响应到服务器的数据端口S<-C)如果服务器的ip为192.168.10.1在H3C 8500的GigabitEthernet 2/1/10 上创建in acl策略允许ftp 主动模式其他禁止:rule permit tcp source 192.168.10.1 0 source-port eq 21 destination-port gt 1024rule permit tcp source 192.168.10.1 0 source-port eq 20 destination-port gt 1024rele deny ip1.2 ftp pasv模式(被动模式)在被动方式FTP中,命令连接和数据连接都由客户端。
FTP客户端的设计与实现
FTP客户端的设计与实现1. 简介FTP(File Transfer Protocol)是一种用于文件传输的标准协议。
FTP客户端是指使用FTP协议与FTP服务器进行通信并传输文件的程序。
在本文中,我们将探讨FTP客户端的设计与实现。
2. 设计2.1 功能需求FTP客户端的主要功能需求包括:1.连接到FTP服务器2.在FTP服务器和本地电脑之间传输文件3.列出FTP服务器上的文件和目录4.创建和删除FTP服务器上的目录5.重命名FTP服务器上的文件6.支持多种操作系统(如Windows、Linux等)2.2 架构设计FTP客户端采用MVC(Model-View-Controller)模式来设计,其中:•Model层:管理FTP客户端的业务与数据逻辑。
提供FTP相关的API,封装了FTP协议的底层实现。
•View层:处理和呈现用户界面。
•Controller层:处理用户请求,调用Model层实现相关业务逻辑。
2.3 技术选型FTP客户端的技术选型如下:•编程语言:Java•GUI框架:JavaFX•FTP库:Apache Commons Net•构建工具:Maven•版本控制:Git2.4 待解决问题FTP客户端在设计中会遇到以下问题:1.如何扩展支持更多的FTP协议?2.如何实现可靠的文件传输?3.如何提高用户界面的体验?3. 实现3.1 界面实现使用JavaFX框架实现FTP客户端的用户界面。
主要界面包括:•登录界面:输入FTP服务器地址、用户名和密码登录FTP服务器。
•主界面:显示FTP服务器上的文件和目录,并提供文件传输和操作的操作界面。
3.2 功能实现FTP客户端通过Apache Commons Net库实现FTP底层协议。
实现的功能包括:1.连接到FTP服务器FTPClient ftp = new FTPClient();ftp.connect(server, port);ftp.login(username, password);2.在FTP服务器和本地电脑之间传输文件ftp.retrieveFile(remoteFile, localFile);ftp.storeFile(remoteFile, localFile);3.列出FTP服务器上的文件和目录FTPFile[] files = ftp.listFiles(remoteDir);4.创建和删除FTP服务器上的目录ftp.mkd(remoteDir);ftp.rmd(remoteDir);5.重命名FTP服务器上的文件ftp.rename(from, to);4. 总结通过对FTP客户端的设计与实现,我们了解了FTP协议的底层实现和FTP客户端的主要功能。
(整理)FTP+SSL服务器及客户端的设置流程.
(整理)FTP+SSL服务器及客户端的设置流程. FTP+SSL服务器及客户端的设置流程⼀、服务器的设置步骤:1、安装IIS7.0的时候勾选上ftp服务器;2、⽤inetmgr打开IIS服务管理器,新建⼀个站点,如下图:3、创建服务器证书,建议是⾃签名证书,如下图:4、双击ftp站点(如erpftp),再双击FTP IPv4地址和域名限制添加要允许访问ftp服务器的客户端ip条⽬如图:5、6、在ftp ssl设置中的SSL证书(S)下选择上⼀步创建的证书,在SSL策略⾥选择【需要SSL连接】,将128为加密⽤于SSL连接前勾选上,如下图:7、在FTP【防⽕墙设置】⾥输⼊外⽹的ip地址如61.158.133.88,点击【应⽤】如下图:8、9、在【在FTP⾝份验证】⾥,启⽤【基本⾝份验证】,禁⽤【匿名⾝份验证】,如下图:10、11、在【FTP授权规则】⾥添加可以访问ftp服务器的账户,并赋予相应的读写权限,如下图:12、在【ftp⽤户隔离】⾥选择【ftp根⽬录】即可,如下图:⼆、三、FTP客户端的设置:⽤cuteftp或ftpxp都可以做ftp+ssl客户端访问下⾯就以cuteftp为例:1、新建⼀个ftp站点,在【常规】在【标签】下的对话框中输⼊服务器的标⽰,在【主机地址】下输⼊服务器的IP,在⽤户名下输⼊允许访问服务器的⽤户,在【密码】下输⼊该账户的密码,在【登录⽅式】选择【标准】点击应⽤.如下图:2、3、4、在【类型】选项卡⾥,在【协议类型(P)】选择【含TLS/SSL的FTP(端⼝990-内在)】,端⼝为990,在【服务器类型】⾥选择【Auto-detect】,在【数据连接类型】⾥选择【使⽤PASV】其他设置不变,最后点多【确定】按钮后再点击【连接】即可5、6、四、在windows2008防⽕墙的⼊站设置⾥可以做如下设置:选择FTP Server Secure(FTP SSL Trafic-In) 并双击其条⽬,选择作⽤域选项卡,在【远程IP地址】的【下列IP地址】添加要限制登录的客户端的ip如59.108.68.66 ,如下图:在【⾼级】选项卡⾥,配置⽂件选择你的外⽹⽹卡锁定的配置⽂件,是公⽤、专⽤还是域,如下图:综述:安装以上三⼤步骤基本上可实现ftp+ssl的设置了。
Windows server 2003搭建ftp服务器步骤
Windows server 2003搭建ftp服务器步骤参考,客户端使用主动模式(Windows server 2003 32/64位)在Windows下搭建ftp服务器可以使用系统自带的ftp服务。
以32 位的Windows server 2003为例,具体步骤如下:第一步:安装ftp服务a. 将i386文件拷贝到服务器上或插入Windows2003安装光盘b. 单击“开始-控制面板-添加或删除程序-添加/删除Windows组件”选项c. 在“组件”列表中,双击“应用程序服务器”选项,单击并选中“Internet 信息服务(IIS)”选项,然后单击“详细信息”按钮,打开“应用程序服务器子组件”窗口。
d. 选中“文件传输协议(FTP) 服务”这个选项,单击确定。
以上步骤如图1所示。
图1e. 单击“下一步”按钮。
出现提示时,如需要文件i386,则定位到刚才拷贝的i386文件,一直点下一步,最后点完成。
第二步:配置ftp站点a. 点击开始-管理工具-Internet 信息服务管理器,如图2所示。
图2b. 右键新建站点,点击下一步,填写FTP 站点描述,如图3。
图3c. 配置IP和端口,也可以选择默认的设置,点击下一步。
如图4。
图4d. 配置FTP用户隔离,选择隔离用户。
如图5。
图5e. 选择FTP的根目录,我在此C盘下新建了一个tmp目录,用它来做ftp的根目录。
设置好之后点击下一步,如图6。
图6f. 配置FTP站点的访问权限,点击下一步。
出现图7所示的界面。
出现这样的提示是因为我们的默认ftp站点是打开的,这个不用管它,点完成就可以了。
图7g. IIS 管理器的界面上,关掉FTP的默认站点,再在tmp站点上右键,点启动,就启动了新建的站点。
如图8。
图8f. 在tmp站点上右键,选择属性,可以配置tmp站点的属性.在这里可以设置ftp的站点目录以及站点目录的访问属性、是否允许匿名登录等属性。
如图9所示。
FTP,SFTP,FTPS总结
FTP,SFTP,FTPS总结FTP应用分FTP,SFTP,FTPS,其中最常见的是FTP,也是下面将重点讨论的情形;SFTP即Secure File Trans f er Protocol,是SSH协议一个子协议,不区分控制和数据端口;FTPS即“FTP-over-SSL”,是在安全套接层使用标准的FTP协议和指令的一种增强型协议(类似https),也没有控制和数据端口的区分;所以SFTP和FTPS完全不同于普通的FTP应用(控制和数据用不同的连接),可以SFTP和FTPS的访问需求等同于普通的TCP应用处理。
主动FT P主动方式的FTP是这样的:客户端从一个任意的非特权端口N(N>;1024)连接到FTP服务器的命令端口,也就是21端口。
然后客户端开始监听端口N+1,并发送FTP命令“port N+1”到FTP服务器。
接着服务器会从它自己的数据端口(20)连接到客户端指定的数据端口(N+1)。
针对FTP服务器前面的防火墙来说,必须允许以下通讯才能支持主动方式FTP:1.任何端口到FTP服务器的21端口(客户端初始化的连接 S<-C)2.FTP服务器的21端口到大于1023的端口(服务器响应客户端的控制端口 S->C)3.FTP服务器的20端口到大于1023的端口(服务器端初始化数据连接到客户端的数据端口 S->C)4.大于1023端口到FTP服务器的20端口(客户端发送ACK响应到服务器的数据端口 S<-C)连接过程大概是下图的样子(没有严格按TCP三次握手画):在第1步中,客户端的命令端口与FTP服务器的命令端口建立连接,并发送命令“POR T1027”。
然后在第2步中,FTP服务器给客户端的命令端口返回一个"ACK"。
在第3步中,FTP服务器发起一个从它自己的数据端口(20)到客户端先前指定的数据端口(1027)的连接,最后客户端在第4步中给服务器端返回一个"ACK"。
cftp协议课程设计
c ftp协议课程设计一、课程目标知识目标:1. 理解FTP协议的基本概念,掌握FTP协议的工作原理;2. 学会使用FTP命令进行文件传输,了解常见的FTP命令及其功能;3. 掌握FTP协议的安全性问题及防范措施。
技能目标:1. 能够独立配置FTP服务器,并进行基本的文件传输操作;2. 能够运用所学知识解决FTP客户端与服务器之间的连接问题;3. 能够分析并解决FTP文件传输过程中出现的问题。
情感态度价值观目标:1. 培养学生主动探索网络协议的兴趣,提高学生的信息素养;2. 增强学生的网络安全意识,使其养成良好的网络行为习惯;3. 培养学生团队协作精神,提高沟通与交流能力。
课程性质:本课程为计算机网络技术与应用课程的一部分,旨在帮助学生掌握FTP协议的基本知识,提高实际操作能力。
学生特点:学生已具备一定的计算机网络基础知识,具有较强的学习能力和动手操作能力。
教学要求:结合课本内容,注重理论与实践相结合,通过实际操作,使学生能够熟练掌握FTP协议的应用。
在教学过程中,关注学生的个体差异,充分调动学生的主观能动性,提高课程教学效果。
将课程目标分解为具体的学习成果,以便进行后续的教学设计和评估。
二、教学内容1. FTP协议基本概念:介绍FTP的定义、作用及其在TCP/IP协议族中的位置;2. FTP工作原理:讲解FTP的连接模式、数据传输方式以及控制通道和数据通道的建立过程;3. FTP命令与操作:详细讲解FTP命令的使用方法,包括登录、下载、上传、删除等操作;4. FTP服务器配置:介绍FTP服务器的安装与配置方法,以及如何设置用户权限和访问控制;5. FTP安全性问题及防范:分析FTP协议的安全隐患,讲解常见的安全防护措施,如SSL/TLS加密、防火墙设置等;6. 实践操作:安排学生进行FTP客户端与服务器之间的文件传输操作,练习使用FTP命令,并针对实际问题进行排查和解决。
教学内容安排与进度:1. 第一课时:FTP协议基本概念与工作原理;2. 第二课时:FTP命令与操作;3. 第三课时:FTP服务器配置与安全性问题;4. 第四课时:实践操作与问题排查。
VisualC网络编程案例实战之FTP客户端实现之二
• 所以我们在使用函数DragEnter()的时候,用到 类CWnd的成员函数ClientToScreen(),将给定 的客户区点坐标转换为屏幕点坐标。最后我们 同样调用类CWnd的成员函数SetCapture(),以 后不管鼠标的位置在哪里,所有的鼠标后续输 入都会被送到当前的窗口处理。
• 调用类CSplitterWnd的成员函数SetRowInfo()和 SetColumnInfo()分别设置分割窗口的行高取值范围、列宽 取值范围。函数原型如下:
• void SetRowInfo( • int row, • int cyIdeal, • int cyMin • ); • void SetColumnInfo( • int col, • int cxIdeal, • int cxMin • ); • 参数含义如下: • row、col:指定分割窗口的行、列,用于定位。
• virtual BOOL CreateView( • int row, • int col, • CRuntimeClass* pViewClass, • SIZE sizeInit, • CCreateContext* pContext • ); • 参数含义如下: • row:指定放置新视图的窗口行。
• 类CTreeCtrl的成员函数GetTreeCtrl()返回树视图控 件的引用。函数OnBegindrag()中结构 NM_TREEVIEW定义如下:
• typedef struct _NM_TREEVIEW { • NMHDR hdr; • UINT action; • TV_ITEM itemOld; • TV_ITEM itemNew; • POINT ptDrag; • } NM_TREEVIEW; • 参数含义如下: • hdr:另一个包含通知消息信息的结构NMHDR。
FTPClient用法
FTPClient⽤法某些数据交换,我们需要通过ftp来完成。
.ftp.FtpClient 可以帮助我们进⾏⼀些简单的ftp客户端功能:下载、上传⽂件。
但如遇到创建⽬录之类的就⽆能为⼒了,我们只好利⽤第三⽅源码,⽐如 .ftp.FTPClient 下⾯写⼀些.ftp.FtpClient 的使⽤⽅法。
1、引⼊包import java.io.DataInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.FileInputStream;import java.util.ArrayList;import java.util.Date;import java.util.List;import .*;import .ftp.FtpClient;2、我们建⼀个叫做FtpUtil的class/*** connectServer* 连接ftp服务器* @throws java.io.IOException* @param path ⽂件夹,空代表根⽬录* @param password 密码* @param user 登陆⽤户* @param server 服务器地址*/public void connectServer(String server, String user, String password, String path)throws IOException{// server:FTP服务器的IP地址;user:登录FTP服务器的⽤户名// password:登录FTP服务器的⽤户名的⼝令;path:FTP服务器上的路径ftpClient = new FtpClient();ftpClient.openServer(server);ftpClient.login(user, password);//path是ftp服务下主⽬录的⼦⽬录if (path.length() != 0) ftpClient.cd(path);//⽤2进制上传、下载ftpClient.binary();}/*** upload* 上传⽂件* @throws ng.Exception* @return -1 ⽂件不存在* -2 ⽂件内容为空* >0 成功上传,返回⽂件的⼤⼩* @param newname 上传后的新⽂件名* @param filename 上传的⽂件*/public long upload(String filename,String newname) throws Exception{long result = 0;TelnetOutputStream os = null;FileInputStream is = null;try {java.io.File file_in = new java.io.File(filename);if (!file_in.exists()) return -1;if (file_in.length()==0) return -2;os = ftpClient.put(newname);result = file_in.length();is = new FileInputStream(file_in);byte[] bytes = new byte[1024];int c;while ((c = is.read(bytes)) != -1) {os.write(bytes, 0, c);}} finally {if (is != null) {is.close();}if (os != null) {os.close();}}return result;}/*** upload* @throws ng.Exception* @return* @param filename*/public long upload(String filename)throws Exception{String newname = "";if (filename.indexOf("/")>-1){newname = filename.substring(stIndexOf("/")+1);}else{newname = filename;}return upload(filename,newname);}/*** download* 从ftp下载⽂件到本地* @throws ng.Exception* @return* @param newfilename 本地⽣成的⽂件名* @param filename 服务器上的⽂件名*/public long download(String filename,String newfilename)throws Exception{long result = 0;TelnetInputStream is = null;FileOutputStream os = null;try{is = ftpClient.get(filename);java.io.File outfile = new java.io.File(newfilename);os = new FileOutputStream(outfile);byte[] bytes = new byte[1024];int c;while ((c = is.read(bytes)) != -1) {os.write(bytes, 0, c);result = result + c;}} catch (IOException e){e.printStackTrace();}finally {if (is != null) {is.close();}if (os != null) {os.close();}}return result;}/*** 取得某个⽬录下的所有⽂件列表**/public List getFileList(String path){List list = new ArrayList();try{DataInputStream dis = new DataInputStream(List(path));String filename = "";while((filename=dis.readLine())!=null){list.add(filename);}} catch (Exception e){e.printStackTrace();}return list;}/*** closeServer* 断开与ftp服务器的链接* @throws java.io.IOException*/public void closeServer()public void closeServer()throws IOException{try{if (ftpClient != null){ftpClient.closeServer();}} catch (IOException e) {e.printStackTrace();}}public static void main(String [] args) throws Exception{FtpUtil ftp = new FtpUtil();try {//连接ftp服务器ftp.connectServer("10.163.7.15", "cxl", "1", "info2");/** 上传⽂件到 info2 ⽂件夹下 */System.out.println("filesize:"+ftp.upload("f:/download/Install.exe")+"字节");/** 取得info2⽂件夹下的所有⽂件列表,并下载到 E盘下 */List list = ftp.getFileList(".");for (int i=0;i<list.size();i++){String filename = (String)list.get(i);System.out.println(filename);ftp.download(filename,"E:/"+filename);}} catch (Exception e) {///}finally{ftp.closeServer();}}}。
FTP客户端源代码C语言
}
szBuffer[ret] = '\0';
printf("%s\n",szBuffer);
if(ret<15)
{
ret = recv(h_Socket4Cmd, szBuffer, DEFAULT_BUFFER_SIZE, 0);
{
pwdfun(h_Socket4Cmd); continue;
}
else if(strncmp(CmdWords,"?",1)==0)
{
helpfun(); continue;
}
else if(strncmp(CmdWords,"quit",4)==0||strncmp(CmdWords,"QUIT",2)==0)
char CmdWords[5],CmdWords2[40];
argv[1]="-s:127.0.0.1";
strcpy(sz_ServIp, &argv[1][3]);
if (WSAStartup(MAKEWORD(2,2), &wsd) != 0) //winsock初始化
{
printf("creating socket failed, error_code : %d\n", WSAGetLastError());
return 1;
}
server.sin_family = AF_INET;
ftp上传时数据Socket错误连接超时的解决方法
ftp上传时数据Socket错误连接超时的解决方法ftp上传时数据Socket错误解决方法一些网友在上传网站时,虽然可以连接但出现如下错误--------------------------------------------200TypesettoASCII.PASV227EnteringPassiveMode(61,151,251,110,4,64).数据Socket错误:连接已失败(连接已拒绝)--------------------------------------------或是-------------------------------------------------命令:>REST0350Restartingat0.SendSTOREorRETRIEVE.命令:>PASV550Passivemodenotallowedonthisserver.错误:>请求的操作未执行(如,文件或目录未找到,不能访问)。
错误:>建立数据socket失败。
-----------------------------------------------------经常登录各种FTP服务器,会遇到socket错误,朋友也经常遇到,来问我。
偏偏大家使用的是不同的FTP软件,所以,今天我把几种目前常用FTP软件的解决办法告诉大家。
★CuteFTP3.5英文版:FTP—>Settings—>Options—>Firewall,将“PASVmode”前复选框中的打勾去掉。
★CuteFTP3.5中文版:FTP—>设置—>选项—>防火墙,“PASV方式(A)”前复选框中的打勾去掉。
★CuteFTP4.0中文版:右击你所建立的ftp站点—>选择属性(properties)—>去掉"usePASVmod"选择项★CuteFTPPro2.0中文版:编辑—>全局设置—>连接—>连接类型,“PASV/PORT”下拉选项菜单选择PORT。
哈工程网络实验FTP服务器和FTP客户端使用实验
二、实验内容:
1.在本机上使用Server-U建立FTP服务器,并熟练设置帐号、目录。
2.使用两种以上ftp客户端软件访问FTP服务器,并学习断点续传功能,理解传输原理。
三、实验环境
Windows XP下的Fielzilla服务器和客户端
四、实验步骤与过程
1.使用服务器端建立FTP服务器,创建用户名为wangzheng,密码18
改进:仅仅设置管理员密码是难以保证安全地,可以在建立FTP服务器的时候对登陆IP以及用户的权限进行更加全面的限制,使得在满足人们的使用需求的同时保证文件和服务器的安全性。
在FTP的服务器端,应该定期对FTP的文件进行安全扫描,努力避免病毒等通过网络传播。
(本页写不下可加页)
五、实验收获、思考与改进
实验收获:
1.通过本次试验学会了如何建立FTP服务器的具体步骤,并对FTP所支持的传输协议有了一定的认识,具有了建立基本FTP服务器的能力。
2.采用不同的FTP软件进行实验,对建立过程的操作更加熟练。
3.采用127.0.0.1本地回环地址和主机地址192.168.1.168进行FTP的测试。,测试均得到很好地结果,印证了实验的正确性
哈尔滨工程大学
《网络实验》
实验报告本
2013~2014学年第一学期
班级
姓名
学号
实验名称
FTP服务器和FTP客户端使用实验
FileZilla FTP服务器源代码分析
FileZilla是一款免费而且开源的FTP工具。
FileZilla是开源的文件传输协议服务器,用C++写的,通过分析它的源代码,可以掌握C++网络编程以及高并发服务器的设计。
FileZilla是上的项目,我们要研究的版本是:FileZilla Server 0_9_18,其实FileZilla还包括客户端软件。
下载后安装,安装时选择安装source,即安装了源代码。
安装完成后,可以直接打开工程自带的FileZilla server.sln,这个是vs 工程,里面有三个project,FZS Interface:这个是文件传输协议服务器的设置以及监控界面Service:这个是核心的文件传输协议服务器部分G文件传输协议:打不开,不知是干什么用的,老外也会如此马虎?:)直接编译是会出错,主要是FileZilla需要依赖两个第三方包:zlib(压缩算法包)以及regexp(正则表达式的包)先搞定zlib,下载、解开,生成目录zlib123,用。
net 2003打开zlib123\projects\visualc6\zlib.dsw打开生成|配置管理器,设置活动的解决方案配置为:DLL Release,编译生成项目zlib,成功后会在目录Win32_DLL_Release下生成zlib1.lib和zlib1.dll然后,regexp用到了boost第三方包,这里面有很多公用的C++组件。
下载、解开后,在cmd下,第一步:需要编译bjm,这是编译boost的编译器,晕cd boost_1_33_1\tools\build\jam_srcbuild.bat在当前的bin.ntx86目录下,生成了bjam.exe文件。
第二步:编译boostcd boost_1_33_1将刚才生成的bjam.exe拷过来set VC7_ROOT="C:\Program Files\Microsoft Visual 2003\Vc7"bjam "-sTOOLS=vc7" install这个步骤需要很久时间,其时我们只用了里面的regexp包,应该可以只编译这个包,但我没细研究。
用标准C语言编写一个ftp协议上传文件的简单程序
sunkaidong 发表于 2008-1-11 12:57
是啊,很困难,但是只有困难才有意思啊.羡慕黑客,不如自己漫漫学习写程序,有一天你会觉得写程序很简单很好玩啊
VxWorks 发表于 2008-1-11 13:06
没有想象中的那么难。给个TCP协议传输数据的例子看看:
服务器端:[code]#include <stdio.h> #include <winsock2.h> #include <time.h> #pragma comment(lib,"ws2_32.lib ")
//构建本地地址信息 saServer.sin_family = AF_INET; saServer.sin_port = htons(SERVER_PORT); saServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
//绑定 ret = bind(sListen,(struct sockaddr *)&saServer,sizeof(saServer)); if( ret == SOCKET_ERROR) {
Sleep((DWORD)100); }
closesocket(sListen); WSACleanup();
puts("press Enter to exit!"); getchar(); return 0;
}[/code]客户端:[code]#include <stdio.h> #include <winsock2.h> #pragma comment(lib,"ws2_32.lib ")
WSACleanup(); printf("socket() failed \n"); return 3; }
CC++实现FTP文件上传下载(转)
CC++实现FTP⽂件上传下载(转)FTP⽂件下载#include <stdio.h>#include <Windows.h>#include <WinInet.h>#pragma comment(lib, "WinInet.lib")BOOL Ftp_SaveToFile(char *pszFileName, BYTE *pData, DWORD dwDataSize){HANDLE hFile = ::CreateFile(pszFileName, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_ARCHIVE, NULL);if (INVALID_HANDLE_VALUE == hFile)return FALSE;DWORD dwRet = 0;WriteFile(hFile, pData, dwDataSize, &dwRet, NULL);CloseHandle(hFile);return TRUE;}BOOL FTP_Download(char *szHostName, char *szUserName, char *szPassword, char *szUrlPath,char *SavePath){HINTERNET hInternet, hConnect, hFTPFile = NULL;BYTE *pDownloadData = NULL;DWORD dwDownloadDataSize = 0;BYTE *pBuf = NULL;DWORD dwBytesReturn = 0;DWORD dwOffset = 0;BOOL bRet = FALSE;hInternet = InternetOpen("WinInet Ftp", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);hConnect = InternetConnect(hInternet, szHostName, INTERNET_INVALID_PORT_NUMBER,szUserName, szPassword, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);hFTPFile = FtpOpenFile(hConnect, szUrlPath, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, NULL); dwDownloadDataSize = FtpGetFileSize(hFTPFile, NULL);pDownloadData = new BYTE[dwDownloadDataSize];RtlZeroMemory(pDownloadData, dwDownloadDataSize);pBuf = new BYTE[4096];RtlZeroMemory(pBuf, 4096);do{bRet = InternetReadFile(hFTPFile, pBuf, 4096, &dwBytesReturn);if (FALSE == bRet)break;RtlCopyMemory((pDownloadData + dwOffset), pBuf, dwBytesReturn);dwOffset = dwOffset + dwBytesReturn;} while (dwDownloadDataSize > dwOffset);Ftp_SaveToFile(SavePath, pDownloadData, dwDownloadDataSize);delete[]pDownloadData;pDownloadData = NULL;return TRUE;}FTP⽂件上传BOOL FTP_Upload(char *szHostName, char *szUserName, char *szPassword, char *szUrlPath, char *FilePath){HINTERNET hInternet, hConnect, hFTPFile = NULL;DWORD dwBytesReturn = 0;DWORD UploadDataSize = 0;BYTE *pUploadData = NULL;DWORD dwRet, bRet = 0;hInternet = ::InternetOpen("WinInet Ftp Upload V1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);hConnect = ::InternetConnect(hInternet, szHostName, INTERNET_INVALID_PORT_NUMBER, szUserName, szPassword,INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);hFTPFile = ::FtpOpenFile(hConnect, szUrlPath, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, NULL); HANDLE hFile = ::CreateFile(FilePath, GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE, NULL);if (INVALID_HANDLE_VALUE == hFile)return FALSE;UploadDataSize = ::GetFileSize(hFile, NULL);pUploadData = new BYTE[UploadDataSize];::ReadFile(hFile, pUploadData, UploadDataSize, &dwRet, NULL);UploadDataSize = dwRet;bRet = ::InternetWriteFile(hFTPFile, pUploadData, UploadDataSize, &dwBytesReturn);if (FALSE == bRet){delete[]pUploadData;return FALSE;}delete[]pUploadData;return TRUE;}int main(int argc,char * argv[]){// FTP主机地址⽤户名密码上传到⽬标FTP⽬录上传的本地⽂件BOOL bRET = FTP_Upload("192.168.1.10", "lyshark", "123321", "/abc.exe","c://nc.exe"); printf("%d \n", bRET);system("pause");return 0;}。
FTP客户端
一、需求分析------------------------------------------21、功能需求2、开发环境与工具3、所需要知识二、知识理解 -----------------------------------------21、FTP实现的基本原理(1)概要(2)上传和下载(3)用户FTP和匿名FTP(4)ASCII和Binary(5)Port和Passive2、WinInet的中FTP的基本操作(1)头文件(2)打开连接和关闭(3)CFtpConnection的操作函数三、完成进度-----------------------------------------51、已完成部分2、未完成部分3、还需改善的部分四、模块化设计---------------------------------------6五、详细设计-----------------------------------------71、CFtpDlg类的一些函数定义 (7)2、CFtpOperate的一些函数定义 (22)六、测试结果----------------------------------------36七、用户手册----------------------------------------40八、实验总结----------------------------------------41九、附录--------------------------------------------41FTP客户端程序一、需求分析1、功能需求(1)实现一个图形用户界面的FTP客户端,保证文件的安全传输和存储。
(2)提供登录界面,上传下载界面、帮助界面、关于界面。
(3)通过输入服务器地址、用户名和密码,可以实现远程FTP主机的登录。
(4)提供本地文件和文件夹的上传功能,可对FTP主机文件进行下载和删除文件。
(5)提供对本地目录的读取与返回,能正确列出文件和文件夹,在没有登录服务器前可以作为一个简单的文件查询工具对本地文件进行查询。
cftpconnection类 实例
英文回答:The cftpconnection class plays a pivotal role in the establishment and management of FTP connections within C++. This class offers aprehensive range of functionalities tailored for connecting to FTP servers, facilitating file transfers, and overseeing the FTP session. By encapsulating the intricacies of the FTP protocol, the cftpconnection class presents a streamlined interface for C++ developers to interface with FTP servers.cftpconnection类在C++内部FTP连接的建立和管理中发挥着关键作用。
该类提供各种功能,用于连接FTP服务器、便利文件传输和监督FTP会话。
通过封装FTP协议的复杂性,cftpconnection类为C++开发者提供了一个简化的界面,与FTP服务器接口。
The cftpconnection class is super important because it lets us connect to FTP servers. We can tell it where the server is, what port to use, and how to log in. Once we're connected, we can use the class to upload, download, and delete files on the server. It also helps us move around the server's folders and change file permissions. So basically, it's like our super handy tool for doing all kinds of stuff on FTP servers.cftpconnection类具有超重要的意义,因为它让我们可以连接到FTP 服务器。
FTP命令详解(含操作实例)
FTP命令详解(含操作实例)操作实例环境:主机(FTP客户端):192.168.65.1 window 7 64bit远程FTP服务器:192.168.65.131 redhat 5 vsftp账号:dylan密码:dylan1 命令行选项1.1 选项介绍我们在命令行用以下选项使用FTP:ftp [-v] [-d] [-i] [-n] [-g] [-s:filename] [-a] [-w:windowsize] [computer]· -v - 禁止显示远程服务器相应信息· -n - 禁止自动登录· -i - 多文件传输过程中关闭交互提示· -d - 启用调试,显示所有客户端与服务器端传递的命令· -g - 禁用文件名通配符,允许在本地文件和路径名中使用· -s:filename - 指定包含 FTP 命令的文本文件;命令在FTP启动后自动运行。
此参数中没有空格。
可替代重定向符(>)使用。
· -a - 在绑字数据连接时使用所有本地接口· -w:windowsize - 覆盖默认的传输缓冲区大小 65535。
· computer - 指定远程电脑计算机名或IP地址。
此参数必须放到最后。
1.2 操作实例-v - 禁止显示远程服务器相应信息使用前:C:\Users\Administrator>ftp 192.168.65.131连接到 192.168.65.131。
220 **************Welcome to blah vsFTP service.*********** ***用户(192.168.65.131:(none)): dylan331 Please specify the password.密码:230 Login successful.ftp> status连接到 192.168.65.131。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
cout << "nReplyCode:" << nReplycode << endl; if (nReplycode == 250)//257:
return false; } //获取FTP服务器数据端口、 unsigned short ServerPort; ServerPort = unsigned short((atoi(part[4]) << 8) + atoi(part[5])); //创建数据连接Socket SocketData = socket(AF_INET, SOCK_STREAM, 0); if (SocketData == INVALID_SOCKET){
if (nConnect == SOCKET_ERROR){ cout << endl << "Server connect error!" << endl; return false;
} return true; }
bool FTPClient::mkdirectory() //FTP服务器发送MKD命令 {
if (!ishavedetail){ cout << "请输入你要创建的文件夹名:"; memset(CmdBuf, 0, MAX_SIZE); cin.getline(CmdBuf, MAX_SIZE, '\n');
} memset(Command, 0, MAX_SIZE); memcpy(Command, "MKD ", strlen("MKD ")); memcpy(Command + strlen("MKD "), CmdBuf, strlen(CmdBuf)); memcpy(Command + strlen("MKD ") + strlen(CmdBuf), "\r\n", 2); //cout<<"Command:"<<Command<<endl; if (!SendCommand())
cout << "Create socket error!" << endl; return false; } //定义Socket地址和端口 sockaddr_in serveraddr2; memset(&serveraddr2, 0, sizeof(serveraddr2)); serveraddr2.sin_family = AF_INET; serveraddr2.sin_port = htons(ServerPort); serveraddr2.sin_addr.S_un.S_addr = inet_addr(ServerAddr); //向FTP服务器发送Connect请求 int nConnect; nConnect = connect(SocketData, (sockaddr*)&serveraddr2, sizeof(serveraddr2));
{
WSADATA WSAData;
//WSADAT:WSADATA结构被用来储存调用
AfxSocketInit全局函数返回的Windows Sockets初始化信息
if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0) //WSAStartup:初始化当前线程通信环境
//向FTP服务器发送PASS命令
void subcommend(string& filepath,string& filename); //输入和转换IP地址
void storfile(char* FTPIP);
//上传文件
void retrfile(char* FTPIP);
//下载文件
void listftp(char* FTPIP);
serveraddr.sin_port = htons(port);//端口
serveraddr.sin_addr.S_un.S_addr = inet_addr(FTPIP);//地址
//向FTP服务器发送Connect请求 cout << "FTP>Control connect..." << endl; int nConnect = connect(SocketControl, (sockaddr*)&serveraddr, sizeof(serveraddr)); if (nConnect == SOCKET_ERROR) {
(1)头文件:FTPClient.h
#include<conio.h>
#define MAX_SIZE 4096
#include<iostream>
#include<winsock2.h>
#include<string>
#include<fstream>
#pragma comment(lib,"ws2_32.lib")
memcpy(Command, "CWD ", strlen("CWD ")); memcpy(Command + strlen("CWD "), CmdBuf, strlen(CmdBuf)); memcpy(Command + strlen("CWD ") + strlen(CmdBuf), "\r\n", 2); if (!SendCommand())
//FTP服务器发送MKD命令
bool changedir();
//FTP服务器发送CWD命令
bool FTPConnection(char* FTPIP,int port); //建立与Socket库绑定
bool useuser();
//向FTP服务器发送USER命令
bool usepass();
//获取PASV命令的应答信息 if (RecvReply()){
if (nReplycode != 227){ cout << "PASV response error!" << endl; closesocket(SocketControl); return false;
} } //分离PASV命令应答信息 char* part[6]; if (strtok(ReplyMsg, "(")) {
bool FTPClient::RecvReply() //控制连接接收 {
int nRecv; memset(ReplyMsg, 0, MAX_SIZE); nRecv = recv(SocketControl, ReplyMsg, MAX_SIZE, 0); if (nRecv == SOCKET_ERROR) {
for (int i = 0; i < 5; i++) {
part[i] = strtok(NULL, ","); if (!part[i])
return false; } part[5] = strtok(NULL, ")"); if (!part[5])
return false; } else {
char ReplyMsg[MAX_SIZE];
private:
int nReplycode;
bool bConnected;
bool buser;
SOCKET SocketControl;
SOCKET SocketData;
};
(2)源文件:FTPClient.cpp
#include<conio.h>
#define MAX_SIZE 4096
#include<iostream>
#include<winsock2.h>
#include<string>
#include<fstream> #include"FTPClient.h" using namespace std; #pragma comment(lib,"ws2_32.lib")
{
cout << "Creat socket error!" << endl;
return false;
}
//定义Socket地址和端口
sockaddr_in serveraddr;
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;//
MAKEWORD:合并短整数
{
cout << "WSAStartup error!" << endl;
return false;
}
//创建控制连接Socket
SocketControl = socket(AF_INET, SOCK_STREAM, 0);
if (SocketControl == INVALID_SOCKET)
return false; //-----------获得MKD命令的应答信息-----------------------if (RecvReply()) {