FTP客户端和服务器源代码(C语言)实现
- 格式:doc
- 大小:104.50 KB
- 文档页数:26
高级计算机程序设计员复习题(含参考答案)一、单选题(共90题,每题1分,共90分)1、()的目的是搞清要解决的问题是什么。
A、问题定义阶段B、需求分析C、软件定义阶段D、可行性研究正确答案:A2、计算机工作原理是建立在()基础上的,逻辑代数是逻辑运算的理论依据。
A、逻辑运算B、集合运算C、数据运算D、物理运算正确答案:A3、()存储一个对话框模板,模板制定了对话框的特征,包括其大小、位置、风格以及对话框中各种控件等。
A、对话框类B、对话框函数C、对话框模板资源D、单模对话框正确答案:C4、下列说法正确的是:()。
A、原型法的指导思想是:自上而下、逐步分解B、结构化分析方法的指导思想是:自上而下、逐步分解C、面向对象分析方法的指导思想是:自上而下、逐步分解D、模块化分析方法的指导思想是:自上而下、逐步分解正确答案:B5、其他模型图的构造和发展依赖于()中所描述的内容。
A、用例图B、状态图C、活动图D、时序图正确答案:A6、已知事务T1和T2是没有加锁的并发操作,T1对某一数据进行写操作,T2对同一数据进行读操作,则可能引发的问题是()。
A、幽灵问题B、丢失修改C、读”脏”数据D、不可重复读正确答案:C7、()适合于检查程序输入条件的各种组合情况。
A、边界值分析法B、错误推测法C、因果图方法D、等价类划分法正确答案:C8、办事公道是指从业人员在进行职业活动时要做到()A、有求必应,服务热情B、奉献社会,助人为乐C、追求真理,坚持原则D、公私分开,实事求是正确答案:C9、命令()用来完成事务,并使事务对数据库所作的修改成为永久的。
A、SaveB、CommitC、UpdateD、Rollback正确答案:B10、用VC实现Ftp查询的程序编写中,如果连接成功,使用()得到服务器的缺省目录。
A、GetCurrentDirectory()B、GetFtpDirectory ()C、GetCurrentHost()D、GetFtpHost()正确答案:A11、目前各部门广泛使用的人事档案管理、财务管理等软件,按计算机应用分类,应属于()。
FTP服务器配置实验报告FTP服务器配置实验报告一、实验目的本实验旨在配置FTP服务器,使其能够实现文件的和功能,以便进行文件传输和共享。
二、实验环境1.操作系统:Windows 102.软件:三、实验步骤1.和安装a.在官方网站的安装包b.打开安装包并按照提示逐步完成安装程序2.配置FTP服务器a.打开软件b.在“编辑”菜单中选择“用户”选项c.“添加”按钮,输入用户名和密码,选择用户权限d.“共享文件夹”选项卡,选择需要共享的文件夹路径e.“限制”选项卡,配置用户的访问限制和配额(可选)f.重复步骤c-e,为其他用户添加配置g.“确定”按钮保存配置3.配置FTP服务器监听端口a.在“编辑”菜单中选择“设置”选项b.在“通用”选项卡中选择需要监听的端口号c.根据需要选择其他设置,如最大连接数和超时时间d.“确定”按钮保存配置4.启动FTP服务器a.在软件中,“服务器”菜单中的“启动”选项b.如果启动成功,将在软件状态栏显示“服务器已启动”信息c.如果启动失败,检查配置是否有误,并重新启动服务器5.连接到FTP服务器a.在本地计算机上打开FTP客户端软件(如)b.输入FTP服务器的IP地质、端口号、用户名和密码c.“连接”按钮,如果连接成功,即可进行文件的和操作四、实验结果与分析根据实验步骤配置FTP服务器后,成功连接到FTP服务器,并能够正常进行文件的和操作。
实验结果表明,FTP服务器配置正确,并具有文件传输和共享功能。
五、实验总结通过本次实验,我掌握了FTP服务器的配置方法,能够实现文件的和功能。
FTP服务器的使用在文件传输和共享方面具有重要意义,能够提高工作效率和数据的安全性。
附件:本文档无附件。
法律名词及注释:1.Transfer Protocol):文件传输协议,用于在计算机之间进行文件的传输和共享。
2.IP地质(Internet Protocol Address):互联网协议地质,用于标识和定位计算机网络中的设备。
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服务器公共部分代码/*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,这⾥就不列出。
QT程序FTP服务器12级电子新能源本2班20120553049张恒一、 QT简介QT是一个跨平台的C++图形化用户界面的应用程序开发框架。
它既可以开发GUI程序,也用于开发非GUI程序,比如控制台工具和服务器。
在QT Creator 3.1.0正式发布后,QT实现了对IOS、Android、WP 的全面支持。
二、 FTP服务器FTP是文件传输协议的英文简称,用于Internet上的控制文件的双向传输。
同多数Internet服务器一样,FTP也是分为两部分,即客户端程序与服务器系统。
本次所做出的图形化界面程序为FTP的客户端程序。
三、程序介绍1.UI介绍FTP客户端程序的UI界面是图所示,在UI中主要由连接、上传、下载、退出、返回、FTP地址、用户名、密码等组成,并且在下方留出大窗口用于显示FTP服务器中的文件。
2.程序源代码介绍3.#include "ftp.h"4.#include "ui_ftp.h"5.6.Ftp::Ftp(QWidget *parent)7.: QWidget(parent), ui(new Ui::Ftp), ftpobj(0)8.{9.ui->setupUi(this);10.//ui->lineEdit->setText("");11.//ui->comboBox->addItem("192.168.1.253");12.ui->lineEdit_3->setEchoMode(QLineEdit::Password);13.//ui->treeWidget->setAcceptDrops(true);14.this->setAcceptDrops(true);15.//model = new QDirModel;16.//ui->treeView->setModel(model);17.//ui->treeView->setAcceptDrops(true);18.19.ui->label_2->setText(tr("Please enter the name of an FTP server."));20.ui->lineEdit_2->setText("");21.ui->lineEdit_3->setText("");22.23.ui->treeWidget->setEnabled(false);24.ui->treeWidget->setRootIsDecorated(false);25.//ui->treeWidget->setHeaderLabels(QStringList() <<tr("Name") <<tr("Size")<<tr("Owner") <<tr("Group") <<tr("Time"));26.ui->treeWidget->header()->setStretchLastSection(false);27.28.ui->pushButton_2->setDefault(true);29.ui->pushButton->setEnabled(false);30.ui->radioButton_2->setChecked(true);31.ui->pushButton_3->setEnabled(false);32.progressDialog = new QProgressDialog(this);33.34.connect(ui->checkBox, SIGNAL(clicked()), this, SLOT(enableCheckBox()));35.connect(ui->treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)),36.this, SLOT(processItem(QTreeWidgetItem *, int)));37.connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *)),38.this, SLOT(enableDownloadButton()));39.connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelDownload()));40.connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(connectOrDisconnect()));41.connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(cdToParent()));42.connect(ui->pushButton_3, SIGNAL(clicked()), this, SLOT(downloadFile()));43.connect(ui->pushButton_4, SIGNAL(clicked()), this, SLOT(close()));44.connect(ui->pushButton_5, SIGNAL(clicked()), this, SLOT(uploadFile()));45.//红色代码用于设置信号槽,定义了PushButton、PushButton_2、PushButton_3等按钮的使用46.setWindowTitle(tr("FTP"));47.}48.49.Ftp::~Ftp()50.{51.delete ui;52.}53.54.55.QSize Ftp::sizeHint() const56.{57.return QSize(500, 300);58.}59.60.//![0]61.void Ftp::connectOrDisconnect()62.{63.if(!ui->checkBox->isChecked()){64.if(ui->lineEdit_2->text().isEmpty()||ui->lineEdit_3->text().isEmpty())65.{66.QMessageBox::information(this, tr("FTP"),tr("请检查ftp账号信息,用户名和密码都不允许为空。
QT程序FTP服务器12级电子新能源本2班20120553049张恒一、 QT简介QT是一个跨平台的C++图形化用户界面的应用程序开发框架。
它既可以开发GUI程序,也用于开发非GUI程序,比如控制台工具和服务器。
在QT Creator 3.1.0正式发布后,QT实现了对IOS、Android、WP 的全面支持。
二、 FTP服务器FTP是文件传输协议的英文简称,用于Internet上的控制文件的双向传输。
同多数Internet服务器一样,FTP也是分为两部分,即客户端程序与服务器系统。
本次所做出的图形化界面程序为FTP的客户端程序。
三、程序介绍1.UI介绍FTP客户端程序的UI界面是图所示,在UI中主要由连接、上传、下载、退出、返回、FTP地址、用户名、密码等组成,并且在下方留出大窗口用于显示FTP服务器中的文件。
2.程序源代码介绍3.#include "ftp.h"4.#include "ui_ftp.h"5.6.Ftp::Ftp(QWidget *parent)7.: QWidget(parent), ui(new Ui::Ftp), ftpobj(0)8.{9.ui->setupUi(this);10.//ui->lineEdit->setText("");11.//ui->comboBox->addItem("192.168.1.253");12.ui->lineEdit_3->setEchoMode(QLineEdit::Password);13.//ui->treeWidget->setAcceptDrops(true);14.this->setAcceptDrops(true);15.//model = new QDirModel;16.//ui->treeView->setModel(model);17.//ui->treeView->setAcceptDrops(true);18.19.ui->label_2->setText(tr("Please enter the name of an FTP server."));20.ui->lineEdit_2->setText("");21.ui->lineEdit_3->setText("");22.23.ui->treeWidget->setEnabled(false);24.ui->treeWidget->setRootIsDecorated(false);25.//ui->treeWidget->setHeaderLabels(QStringList() <<tr("Name") <<tr("Size")<<tr("Owner") <<tr("Group") <<tr("Time"));26.ui->treeWidget->header()->setStretchLastSection(false);27.28.ui->pushButton_2->setDefault(true);29.ui->pushButton->setEnabled(false);30.ui->radioButton_2->setChecked(true);31.ui->pushButton_3->setEnabled(false);32.progressDialog = new QProgressDialog(this);33.34.connect(ui->checkBox, SIGNAL(clicked()), this, SLOT(enableCheckBox()));35.connect(ui->treeWidget, SIGNAL(itemActivated(QTreeWidgetItem *, int)),36.this, SLOT(processItem(QTreeWidgetItem *, int)));37.connect(ui->treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem *,QTreeWidgetItem *)),38.this, SLOT(enableDownloadButton()));39.connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelDownload()));40.connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(connectOrDisconnect()));41.connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(cdToParent()));42.connect(ui->pushButton_3, SIGNAL(clicked()), this, SLOT(downloadFile()));43.connect(ui->pushButton_4, SIGNAL(clicked()), this, SLOT(close()));44.connect(ui->pushButton_5, SIGNAL(clicked()), this, SLOT(uploadFile()));45.//红色代码用于设置信号槽,定义了PushButton、PushButton_2、PushButton_3等按钮的使用46.setWindowTitle(tr("FTP"));47.}48.49.Ftp::~Ftp()50.{51.delete ui;52.}53.54.55.QSize Ftp::sizeHint() const56.{57.return QSize(500, 300);58.}59.60.//![0]61.void Ftp::connectOrDisconnect()62.{63.if(!ui->checkBox->isChecked()){64.if(ui->lineEdit_2->text().isEmpty()||ui->lineEdit_3->text().isEmpty())65.{66.QMessageBox::information(this, tr("FTP"),tr("请检查ftp账号信息,用户名和密码都不允许为空。
FTP客户端的设计与实现摘要FTP是Internet上用来传送文件的协议。
它是为了我们能够在Internet上互相传送文件而制定的文件传送标准,规定了Internet上文件如何传送.通过FTP协议,我们就可以跟Internet上的FTP服务器进行文件的上传或下载。
本设计以实现一个简单易用的FTP客户端为目标,通过分析FTP协议的基本工作原理和FTP的数据传输原理,研究如何使用VC++语言对FTP客户端进行设计,用Visual Studio2010设计和实现了FTP客户端的开发。
关键词FTP的工作原理;VC++;FTP客户端1绪论1。
1 课题背景FTP是互联网上使用最广泛的文件传输协议[1].在互联网早期曾占据整个互联网通信的三分之一,它解决了在不同操作系统下处理文件格式的不兼容性。
传统方式需要在DOS 下输入命令,对于普通用户是件极困难的事。
但有了FTP客户端软件后,只要轻点几下鼠标就可以完成所有操作。
FTP客户端应该包含以下功能:登录,浏览目录,上传和下载[2]。
它已成为人们不可缺少的软件之一.1。
2 研究现状FTP服务是Internet上最早应用于主机之间进行数据传输的基本服务之一。
起初,FTP 并不是应用于IP网络上的协议,而是20世纪60~80年代美国国防部组建的ARPANET网络中,用于计算机间的文件传输的协议。
FTP服务的一个非常重要的特点是其实现可以独立于平台,也就是说在UNIX、DOS、Windows等操作系统中都可以实现FTP的客户端和服务器[3]。
尽管目前已经普遍采用HTTP方式传送文件,但FTP仍然是跨平台直接传送文件的主要方式。
目前市面上可通过正规渠道获得的成熟的FTP软件如Server-U、Cuteftp、Transmit、Flashfxp等都是国外开发的,需要注册、付费使用。
从其他渠道获取的FTP软件,则存在安全方面的问题。
国内也很难找到免费、安全的FTP软件。
虽然操作系统有自带的FTP软件,但它是基于命令行的,没有友好的用户操作界面,对用户的计算机技能要求较高,一般的用户也不会用,而且不支持断点续传和文件夹的上传、下载等功能[4]。
FileZilla FTP服务器源代码分析:FileZilla是⼀款免费⽽且开源的FTP⼯具。
包括FileZilla Client,FileZilla Server两个版本。
FileZilla Server只提供了windows系统下的版本,我们要将本地的站页⽂件上传到站服务器,或从服务器下载页⽂件,只需FileZilla Client客户端版本就可以了。
FileZilla FTP服务器源代码分析FileZilla是开源的FTP服务器,⽤C++写的,通过分析它的源代码,可以掌握C++络编程以及⾼并发服务器的设计。
FileZilla是上的项⽬,我们要研究的版本是:FileZilla Server 0_9_18,其实FileZilla还包括客户端软件。
下载后安装,安装时选择安装source,即安装了源代码。
安装完成后,可以直接打开⼯程⾃带的FileZilla server.sln,这个是vs ⼯程,⾥⾯有三个project,FZS Interface:这个是FTP服务器的设置以及监控界⾯Service:这个是核⼼的FTP服务器部分GFtp:打不开,不知是⼲什么⽤的,⽼外也会如此马虎? :)直接编译是会出错,主要是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⽂件。
F T P服务器端源代码作者:李扬FTP Server源代码解决方案管理器主界面:using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Collections;using .Sockets;using ;using System.Threading;using System.Diagnostics;namespace FtpServer{public partial class FtpServerForm : Form{//================================================================================================ #region Members//服务器默认目录public const string ROOT_DIR = "e:\\";//服务器可以支持的最多的客户端的连接数public const int MAX_NUM = 100;//clients数组保存当前在线用户的Client对象internal static Hashtable clients = new Hashtable();//该服务器默认的监听的端口号private TcpListener listener;//开始服务的标志internal static bool SocketServiceFlag = false;//服务器的IP地址internal string ip;internal int port;#endregion Members//------------------------------------------------------------------------------------------------#region Delegatesdelegate void AddClientDelegate(Client client);delegate void RemoveClientDelegate(Client client);delegate void AddLogDelegate(string msgLog);#endregion Delegate//----------------------------------------------------------------------------------------------#region Properties#endregion Properties//================================================================================================ #region Constructorspublic FtpServerForm(){InitializeComponent();//对控件的操作都改为异步操作,所以不需要设置:// Control.CheckForIllegalCrossThreadCalls = false;}#endregion Constructors//------------------------------------------------------------------------------------------------#region Internal Methods#endregion//------------------------------------------------------------------------------------------------#region Private Methods/// <summary>/// 获取有效的端口号/// </summary>/// <param name="port"></param>/// <returns></returns>private int getValidPort(string port){int lport;try{if (port == string.Empty)throw new ArgumentException("端口号为空,不能启动服务器!");lport = Convert.ToInt32(port);}catch (Exception ex){AddLog("无效端口号:" + ex.ToString());return -1;}return lport;}//在新的线程中的操作,主要用于当接受到一个客户端请求时确认与客户端的连接,//并且立刻启动一个新的线程来处理与该客户的信息交互private void StartSocketListen(){while (FtpServerForm.SocketServiceFlag){try{//当接收到一个客户端请求时,确认与客户端的连接if (listener.Pending()){Socket socket = listener.AcceptSocket();if (clients.Count >= MAX_NUM){AddLog("已经达到最大连接数" + MAX_NUM + "拒绝新的连接!");socket.Close();}else{//启动一个新的线程,//执行方法this.ServiceClient,处理用户相应的请求Client client = new Client(this, socket);AsyncAddClient(client);Thread clientService = new Thread(new ThreadStart(client.ServiceClient));clientService.Start();}}Thread.Sleep(500);}catch (Exception e){AddLog(e.ToString());}}}private void AsyncAddClient(Client client){AddClientDelegate addClient = new AddClientDelegate(AddClient);this.BeginInvoke(addClient, client);}private void AddClient(Client client){//确保在用户界面线程上Debug.Assert(this.InvokeRequired == false);if (clients.Contains(client.IpAddress)){clients.Remove(client.IpAddress);}if (lbClients.Items.IndexOf(client.IpAddress) > -1){lbClients.Items.Remove(client.IpAddress);}clients.Add(client.IpAddress, client);lbClients.Items.Add(client.IpAddress);this.tbClientsNum.Text = Convert.ToString(clients.Count);}private void RemoveClient(Client client){//确保在用户界面线程上Debug.Assert(this.InvokeRequired == false);if (clients.Contains(client.IpAddress)){clients.Remove(client.IpAddress);lbClients.Items.Remove(client.IpAddress);}tbClientsNum.Text = Convert.ToString(clients.Count);}private void addmsgLog(string msgLog){//确保在用户界面线程上Debug.Assert(this.InvokeRequired == false);this.txtmsgLog.Text += msgLog + "\r\n";}#endregion Private Methods//------------------------------------------------------------------------------------------------#region Public Methodspublic void AsyncRemoveClient(Client client){RemoveClientDelegate removeClient = new RemoveClientDelegate(RemoveClient);this.BeginInvoke(removeClient, client);}public void AddLog(string msgLog){AddLogDelegate AddLog = new AddLogDelegate(addmsgLog);this.BeginInvoke(AddLog, msgLog);}#endregion Public Methods//================================================================================================ #region Eventsprivate void tbSocketPort_TextChanged(object sender, EventArgs e){this.btnStart.Enabled = (this.tbSocketPort.Text != string.Empty);}private void btnStart_Click(object sender, EventArgs e){AddLog("FTP服务器启动……");port = getValidPort(tbSocketPort.Text);if (port < 0)return;//获得本机局域网IP地址IPAddress[] AddressList =Dns.GetHostByName(Dns.GetHostName()).AddressList;if (AddressList.Length > 0){ip = AddressList[0].ToString();try{IPAddress ipAdd = IPAddress.Parse(ip);//创建服务器套接字listener = new TcpListener(ipAdd, port);//开始监听服务器端口listener.Start();//启动一个新的线程,执行方法this.StartSocketListen,//以便在一个独立的进程中执行确认与客户端Socket连接的操作FtpServerForm.SocketServiceFlag = true;Thread thread = new Thread(newThreadStart(this.StartSocketListen));thread.Start();this.btnStart.Enabled = false;this.btnStop.Enabled = true;this.tbSocketPort.Enabled = false;}catch (Exception ex){AddLog(ex.ToString());}}}private void btnStop_Click(object sender, EventArgs e){FtpServerForm.SocketServiceFlag = false;this.btnStart.Enabled = true;this.btnStop.Enabled = false;this.tbSocketPort.Enabled = true;if (listener != null){listener.Stop();}System.Collections.IDictionaryEnumerator myEnumerator =clients.GetEnumerator();while (myEnumerator.MoveNext()){Client client = (Client)myEnumerator.Value;client.StopFlag = true;client.CurrentSocket.Close();}clients.Clear();lbClients.Items.Clear();this.tbClientsNum.Text = "";}private void FtpServerForm_FormClosing(object sender, FormClosingEventArgs e){btnStop_Click(sender, e);}private void txtmsgLog_TextChanged(object sender, EventArgs e){this.txtmsgLog.SelectionStart = this.txtmsgLog.Text.Length;this.txtmsgLog.SelectionLength = 0;this.txtmsgLog.ScrollToCaret();}#endregion Events//============================================================================================== }}Client.cs类源代码using System;using System.Collections.Generic;using System.Linq;using System.Text;using .Sockets;using ;using System.Threading;namespace FtpServer{public class Client{//================================================================================================ #region Membersint dataPort = 5380;//21,21internal FtpServerForm server;private Request request;//当前的连接状态internal bool isLogin = false;//工作的目录internal string workingDir;private string user;private string password;private Socket currentSocket;private string ipAddress;private int port;private bool stopFlag;private string fileName;private string currentCmd;#endregion Members//------------------------------------------------------------------------------------------------ #region Properties/// <summary>/// 封装用户名/// </summary>public string User{get { return user; }set { user = value; }}/// <summary>/// 封装登陆密码/// </summary>public string Password{get { return password; }set { password = value; }}/// <summary>/// 封装与客户端连接的Socket/// </summary>public Socket CurrentSocket{get { return currentSocket; }set { currentSocket = value; } }/// <summary>/// 封装IP地址/// </summary>public string IpAddress{get { return ipAddress; }set { ipAddress = value; }}/// <summary>/// 封装端口号/// </summary>public int Port{get { return port; }set { port = value; }}/// <summary>/// 封装停止标志/// </summary>public bool StopFlag{get { return stopFlag; }set { stopFlag = value; }}/// <summary>/// 封装文件名/// </summary>public string FileName{get { return fileName; }set { fileName = value; }}/// <summary>/// 封装当前命令/// </summary>public string CurrentCmd{get { return currentCmd; }set { currentCmd = value; } }#endregion Properties//================================================================================================ #region Constructorspublic Client(FtpServerForm server, Socket clientSocket){this.server = server;this.currentSocket = clientSocket;ipAddress = gerRemoteIPAddress();port = server.port;request = new Request(this);workingDir = FtpServerForm.ROOT_DIR;}#endregion Constructors//------------------------------------------------------------------------------------------------#region Internal Methodsinternal void sendMsg(string msg){string resmsg = msg + "\r\n";System.Byte[] message = System.Text.Encoding.Default.GetBytes(resmsg.ToCharArray());currentSocket.Send(message, message.Length, 0);}internal void sendMsgByTempSocket(string msg){System.Byte[] message = System.Text.Encoding.Default.GetBytes(msg.ToCharArray());sendMsgByTempSocket(message);}internal void sendMsgByTempSocket(byte[] msg){Socket tempSocket = getTempSocket();if (tempSocket.Connected){tempSocket.Send(msg, msg.Length, 0);}tempSocket.Close();}internal Socket getTempSocket(){Socket tempSocket = null;if (request.transferType == Request.PASV){IPAddress ipAdd = IPAddress.Parse(server.ip);//监听器TcpListener listener = new TcpListener(ipAdd, dataPort);//开始监听服务器端口listener.Start();int timeout = 5000;while (timeout-- > 0){if (listener.Pending()){tempSocket = listener.AcceptSocket();break;}try{Thread.Sleep(500);}catch (Exception e){sendLogToServer(e.ToString());}}}else{tempSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);tempSocket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.SendTimeout, 1000);IPAddress ipAdd = IPAddress.Parse(this.ipAddress);IPEndPoint hostEndPoint = new IPEndPoint(ipAdd, port);tempSocket.Connect(hostEndPoint);}return tempSocket;}#endregion//------------------------------------------------------------------------------------------------ #region Private Methodsprivate string gerRemoteIPAddress(){return ((IPEndPoint)currentSocket.RemoteEndPoint).Address.ToString(); }private string[] receiveCmd(){string[] tokens = null;//接收数据并存入buff数组中byte[] buff = new byte[1024];currentSocket.Receive(buff);//将字符数组转化为字符串string clientCommand = System.Text.Encoding.Default.GetString(buff);clientCommand = clientCommand.Trim("\0".ToCharArray());clientCommand = clientCommand.Trim("\r\n".ToCharArray());if (clientCommand.Length > 0){//tokens[0]中保存了命令标志符(LIST、DIR、RETR或QUIT)if (clientCommand.IndexOf(" ") > -1){tokens = clientCommand.Split(new Char[] { ' ' }, 2);}else{tokens = clientCommand.Split("\r\n".ToCharArray());}this.currentCmd = tokens[0];}return tokens;}#endregion Private Methods//------------------------------------------------------------------------------------------------#region Public Methodspublic void sendLogToServer(string msgLog){if (server != null)server.AddLog(msgLog);}public void ServiceClient(){stopFlag = false;isLogin = false;//发送欢迎消息sendMsg("220 欢迎使用FTP服务器,您已经连接上了服务器!\r\n"+"★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r\n" +" Mail: liyangforever@ \r\n" +" QQ: 403760530 \r\n" +" Created by andy $12:53 2009-6-13$ \r\n" +" Copyright (C) 2008-2009 All rights reserved \r\n" +"★★★★★★★★★★★★★★★★★★★★★★★★★★★★★");{//用户名if (request.parseCmd(receiveCmd()) != Request.LOGIN_USER){sendMsg("221 命令错误!");this.CurrentSocket.Close();server.AsyncRemoveClient(this);return;}sendMsg("331 请输入用户" + User + "的登录密码");//密码if (request.parseCmd(receiveCmd()) != Request.LOGIN_PASS){sendMsg("221 命令错误");this.CurrentSocket.Close();server.AsyncRemoveClient(this);return;}//判断用户名、密码是否正确if ((user == "anonymous") && (password == "someone@")) {this.isLogin = true;sendMsg("230 User " + User + "已经登录.");}else{sendMsg("530 用户名或密码错误");currentSocket.Close();server.AsyncRemoveClient(this);return;}}catch (Exception e){sendLogToServer(e.ToString());this.CurrentSocket.Close();server.AsyncRemoveClient(this);return;}while (!stopFlag && FtpServerForm.SocketServiceFlag){if (!isLogin){break;}tryif (currentSocket.Connected && currentSocket.Available > 0){request.parseCmd(receiveCmd());}Thread.Sleep(500);}catch (Exception e){sendLogToServer("发生异常" + e.ToString());this.CurrentSocket.Close();server.AsyncRemoveClient(this);break;}}this.CurrentSocket.Close();server.AsyncRemoveClient(this);}#endregion Public Methods//================================================================================================ }}Request.cs类源代码using System;using System.Collections.Generic;using System.Linq;using System.Text;using .Sockets;using ;using System.Threading;namespace FtpServer{public class Client{//================================================================================================ #region Membersint dataPort = 5380;//21,21internal FtpServerForm server;private Request request;//当前的连接状态internal bool isLogin = false;//工作的目录internal string workingDir;private string user;private string password;private Socket currentSocket;private string ipAddress;private int port;private bool stopFlag;private string fileName;private string currentCmd;#endregion Members//------------------------------------------------------------------------------------------------ #region Properties/// <summary>/// 封装用户名/// </summary>public string User{get { return user; }set { user = value; }}/// <summary>/// 封装登陆密码/// </summary>public string Password{get { return password; }set { password = value; }}/// <summary>/// 封装与客户端连接的Socket/// </summary>public Socket CurrentSocket{get { return currentSocket; }set { currentSocket = value; }}/// <summary>/// 封装IP地址/// </summary>public string IpAddress{get { return ipAddress; }set { ipAddress = value; } }/// <summary>/// 封装端口号/// </summary>public int Port{get { return port; }set { port = value; }}/// <summary>/// 封装停止标志/// </summary>public bool StopFlag{get { return stopFlag; }set { stopFlag = value; }}/// <summary>/// 封装文件名/// </summary>public string FileName{get { return fileName; }set { fileName = value; } }/// <summary>/// 封装当前命令/// </summary>public string CurrentCmd{get { return currentCmd; }set { currentCmd = value; } }#endregion Properties//================================================================================================ #region Constructorspublic Client(FtpServerForm server, Socket clientSocket){this.server = server;this.currentSocket = clientSocket;ipAddress = gerRemoteIPAddress();port = server.port;request = new Request(this);workingDir = FtpServerForm.ROOT_DIR;}#endregion Constructors//------------------------------------------------------------------------------------------------#region Internal Methodsinternal void sendMsg(string msg){string resmsg = msg + "\r\n";System.Byte[] message = System.Text.Encoding.Default.GetBytes(resmsg.ToCharArray());currentSocket.Send(message, message.Length, 0);}internal void sendMsgByTempSocket(string msg){System.Byte[] message = System.Text.Encoding.Default.GetBytes(msg.ToCharArray());sendMsgByTempSocket(message);}internal void sendMsgByTempSocket(byte[] msg){Socket tempSocket = getTempSocket();if (tempSocket.Connected){tempSocket.Send(msg, msg.Length, 0);}tempSocket.Close();}internal Socket getTempSocket(){Socket tempSocket = null;if (request.transferType == Request.PASV){IPAddress ipAdd = IPAddress.Parse(server.ip);//监听器TcpListener listener = new TcpListener(ipAdd, dataPort);//开始监听服务器端口listener.Start();int timeout = 5000;while (timeout-- > 0){if (listener.Pending()){tempSocket = listener.AcceptSocket();break;}try{Thread.Sleep(500);}catch (Exception e){sendLogToServer(e.ToString());}}}else{tempSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);tempSocket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.SendTimeout, 1000);IPAddress ipAdd = IPAddress.Parse(this.ipAddress);IPEndPoint hostEndPoint = new IPEndPoint(ipAdd, port);tempSocket.Connect(hostEndPoint);}return tempSocket;}#endregion//------------------------------------------------------------------------------------------------ #region Private Methodsprivate string gerRemoteIPAddress(){return ((IPEndPoint)currentSocket.RemoteEndPoint).Address.ToString(); }private string[] receiveCmd(){string[] tokens = null;//接收数据并存入buff数组中byte[] buff = new byte[1024];currentSocket.Receive(buff);//将字符数组转化为字符串string clientCommand = System.Text.Encoding.Default.GetString(buff);clientCommand = clientCommand.Trim("\0".ToCharArray());clientCommand = clientCommand.Trim("\r\n".ToCharArray());if (clientCommand.Length > 0){//tokens[0]中保存了命令标志符(LIST、DIR、RETR或QUIT)if (clientCommand.IndexOf(" ") > -1){tokens = clientCommand.Split(new Char[] { ' ' }, 2);}else{tokens = clientCommand.Split("\r\n".ToCharArray());}this.currentCmd = tokens[0];}return tokens;}#endregion Private Methods//------------------------------------------------------------------------------------------------#region Public Methodspublic void sendLogToServer(string msgLog){if (server != null)server.AddLog(msgLog);}public void ServiceClient(){stopFlag = false;isLogin = false;//发送欢迎消息sendMsg("220 欢迎使用FTP服务器,您已经连接上了服务器!\r\n"+"★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r\n" +" Mail: liyangforever@ \r\n" +" QQ: 403760530 \r\n" +" Created by andy $12:53 2009-6-13$ \r\n" +" Copyright (C) 2008-2009 All rights reserved \r\n" +"★★★★★★★★★★★★★★★★★★★★★★★★★★★★★");try{//用户名if (request.parseCmd(receiveCmd()) != Request.LOGIN_USER){sendMsg("221 命令错误!");this.CurrentSocket.Close();server.AsyncRemoveClient(this);return;}sendMsg("331 请输入用户" + User + "的登录密码");//密码if (request.parseCmd(receiveCmd()) != Request.LOGIN_PASS){sendMsg("221 命令错误");this.CurrentSocket.Close();server.AsyncRemoveClient(this);return;}//判断用户名、密码是否正确if ((user == "anonymous") && (password == "someone@")) {this.isLogin = true;sendMsg("230 User " + User + "已经登录.");}else{sendMsg("530 用户名或密码错误");currentSocket.Close();server.AsyncRemoveClient(this);return;}}catch (Exception e){sendLogToServer(e.ToString());this.CurrentSocket.Close();server.AsyncRemoveClient(this);return;}while (!stopFlag && FtpServerForm.SocketServiceFlag){if (!isLogin){break;}try{if (currentSocket.Connected && currentSocket.Available > 0){request.parseCmd(receiveCmd());}Thread.Sleep(500);}catch (Exception e){sendLogToServer("发生异常" + e.ToString());this.CurrentSocket.Close();server.AsyncRemoveClient(this);break;}}this.CurrentSocket.Close();server.AsyncRemoveClient(this);}#endregion Public Methods//================================================================================================ }}。
一、编写FTP服务器:二、连接协议:所有ftp协议没有2进制数字,全部用文本格式收发。
发送协议:协议号+描述+CRLF接收协议:协议键+描述+CRLF其中,协议号和协议键是关键字,不能随意变换。
#define CRLF “\r\n”CRLF作为校验使用,因此是必须出现在发送或者接收字串的结尾。
发送长度必须等于strlen或者string.length。
发送长度也是校验条件之一。
协议键不区分大小写给以处理。
例如:创建ftp端口21,使用IE浏览器执行登录。
收到Accept连接后立即返回Send1,之后使用Receive接收你将收到Recv2。
依次向下收发,得到的测试结果如下:Send1=220 127.0.0.1 FtpD for freeRecv2=USER testSend3=331 Password required for test .Recv4=PASS testSend5=230 User test logged in , proceedRecv6=opts utf8 onSend7=502 Command OPTS utf8 on not implementedRecv8=systSend9=215 WindowsRecv10=site helpSend11=502 Command SITE help not implementedRecv12=PWDSend13=257 "/" is current directoryRecv14=CWD /subing/Send15=250 "/subing/" is current directory.Recv16=TYPE ASend17=200 Type set to ASCII.Recv18=PASVSend19=425 Cannot open data connection (192.168.1.13 0 create failed)Recv20=TYPE ASend21=200 Type set to ASCII.Recv22=PORT 127,0,0,1,4,226Send23=200 Port command okay.Recv24=LISTSend25=150 Opening ASCII NO-PRINT mode data connection for ls -l.三、协议内容:每一个协议都是一个判断分支语句,得到是或否的结果再返回(发送)。
linux c 基于libcurl 库的ftp上传和下载代码/zengraoli/article/details/115173672013昨天考虑好了IM传送图片的方式,用的是FTP做缓存来传递图片,以减少聊天服务器的压力,用的是libcurl库,自己下载了一个Server-U 服务器,下面是测试程序,上传和下载都跑通了,剩下的就是在程序中写逻辑来实现具体的功能了。
上传代码:[cpp] view plain copy print?//ftp上传实例// 服务器地址:192.168.0.185 账号:spider 密码:spider // 在服务器路径a 上建立一个a.txt ,本地文件是test.txt // 命令行参数192.168.0.185 spider spider a a.txt D:/test.txt //#include<stdlib.h> //#include <stdio.h> //#include <curl/curl.h> //#include <string.h> // //int debugFun(CURL* curl, curl_infotype type, char* str, size_t len, void* stream) //{ // //只打印CURLINFO_TEXT 类型的信息// if(type == CURLINFO_TEXT) // { // fwrite(str, 1, len, (FILE*)stream); // } // return 0; //} // //int main(int argc, char** argv)//{ // CURL* curl; // CURLcode res; // char errorBuf[CURL_ERROR_SIZE]; // FILE*sendFile, *debugFile; // char ftpurl[256 + 1]; // char usrpasswd[64 + 1]; // // curl_slist *slist=NULL; // // if(argc != 7) // { //printf("Usage:\n\t./ftp ip username password ftpPath destFileName srcFile"); // return -1; // } // // //将相关的调试信息打印到dubugFile.txt中//if(NULL == (debugFile = fopen("debugFile.txt", "a+"))) // return -1; // // //打开ftp上传的源文件//if(NULL == (sendFile = fopen(argv[6], "r"))) // { // fclose(debugFile); // return -1; // } // // //获取需要发送文件的大小// fseek(sendFile, 0, SEEK_END); // int sendSize = ftell(sendFile); //if(sendSize < 0) // { //fclose(debugFile); // fclose(sendFile); // return -1; // } // fseek(sendFile, 0L,SEEK_SET); // // if((res =curl_global_init(CURL_GLOBAL_ALL)) != 0) //{ // fclose(debugFile); //fclose(sendFile); // return -1; // } //if((curl = curl_easy_init()) == NULL) // { // fclose(debugFile); // fclose(sendFile); //curl_global_cleanup(); // return -1; // }// // if(argv[4][strlen(argv[4]) - 1] != '/') //sprintf(ftpurl, "ftp://%s/%s/%s", argv[1], argv[4], argv[5]);// else // sprintf(ftpurl, "ftp://%s/%s%s",argv[1], argv[4], argv[5]); // curl_easy_setopt(curl, CURLOPT_URL, ftpurl); // //设置ftp上传url,组成如下的URL ////ftp://192.168.31.145//root/subdir/curl/testftp.txt // // sprintf(usrpasswd, "%s:%s", argv[2], argv[3]); //curl_easy_setopt(curl, CURLOPT_USERPWD, usrpasswd);// // curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); // curl_easy_setopt(curl, CURLOPT_DEBUGDATA, debugFile); // // curl_easy_setopt(curl,CURLOPT_READDATA, sendFile); //curl_easy_setopt(curl, CURLOPT_UPLOAD, 1); //curl_easy_setopt(curl, CURLOPT_INFILESIZE, sendSize);// curl_easy_setopt(curl,CURLOPT_FTP_CREATE_MISSING_DIRS, 1); // // curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debugFun); // // res = curl_easy_perform(curl); // if(0 != res) // { // fclose(sendFile); // fclose(debugFile); // curl_easy_cleanup(curl);// curl_global_cleanup(); // return -1;// } // // curl_easy_cleanup(curl); //fclose(sendFile); // fclose(debugFile); //curl_global_cleanup(); // getchar(); // return 0;//}下载代码如下:[cpp] view plain copy print?//ftp下载实例#include <stdio.h>; #include <curl/curl.h>;#include <curl/types.h>; #include <curl/easy.h>; struct FtpFile //定义一个结构为了传递给my_fwrite函数.可用curl_easy_setopt的CURLOPT_WRITEDATA选项传递{ char *filename; FILE *stream; }; int my_fwrite(void *buffer, size_t size, size_t nmemb, void*stream) { struct FtpFile *out=(struct FtpFile *)stream; // stream指针其实就是指向struct FtpFile ftpfile的if(out && !out->stream){ out->stream=fopen(out->filenam e, "wb"); //没有这个流的话就创建一个名字是out->filename. if(!out->stream) return -1; } return fwrite(buffer, size, nmemb, out->stream); } int main(int argc, char*argv[]) { CURL *curl;CURLcode res; struct FtpFileftpfile={"D:/Success.txt",NULL}; //初始化一个FtpFile结构curl_global_init(CURL_GLOBAL_DEFAULT);curl = curl_easy_init(); if(curl){ curl_easy_setopt(curl,CURLOPT_URL,"ftp://192.168.0.185/a/a.txt");curl_easy_setopt(curl, CURLOPT_USERPWD,"spider:spider"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,my_fwrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile); //给相关函数的第四个参数传递一个结构体的指针curl_easy_setopt(curl, CURLOPT_VERBOSE,TRUE);//CURLOPT_VERBOSE 这个选项很常用用来在屏幕上显示对服务器相关操作返回的信息res = curl_easy_perform(curl);curl_easy_cleanup(curl);if(CURLE_OK != res)fprintf(stderr, "curl told us %d\n", res); }if(ftpfile.stream) fclose(ftpfile.stream);curl_global_cleanup(); return 0; }最后记录一个比较好用的:[cpp] view plain copyprint?#include <stdlib.h> #include <stdio.h>#include <curl/curl.h> #include <sys/stat.h> /* parse headers for Content-Length */ size_t getcontentlengthfunc(void *ptr, size_t size, size_t nmemb, void *stream) { int r; long len = 0; /*_snscanf() is Win32 specific */ //r = _snscanf(ptr, size * nmemb, "Content-Length: %ld\n", &len); r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len); if (r) /* Microsoft: we don't read the specs */ *((long *) stream) = len; return size * nmemb; } /* discard downloaded data */ size_t discardfunc(void *ptr, size_t size, size_t nmemb, void *stream) { return size * nmemb; } //write data to upload size_t writefunc(void *ptr, size_t size, size_t nmemb, void *stream) { return fwrite(ptr, size, nmemb, (FILE*)stream); } /* read data to upload */ size_t readfunc(void *ptr, size_t size, size_t nmemb, void *stream) { FILE *f = (FILE*)stream; size_t n; if (ferror(f)) returnCURL_READFUNC_ABORT; n = fread(ptr, size, nmemb, f) * size; return n; } int upload(CURL*curlhandle, const char * remotepath, const char * localpath, long timeout, long tries) { FILE *f; long uploaded_len = 0; CURLcode r =CURLE_GOT_NOTHING; int c; f =fopen(localpath, "rb"); if (f == NULL){ perror(NULL); return 0; }curl_easy_setopt(curlhandle, CURLOPT_UPLOAD, 1L);curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath); curl_easy_setopt(curlhandle, CURLOPT_USERPWD, "spider:spider"); if (timeout)curl_easy_setopt(curlhandle,CURLOPT_FTP_RESPONSE_TIMEOUT, timeout);curl_easy_setopt(curlhandle, CURLOPT_HEADERFUNCTION, getcontentlengthfunc); curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA, &uploaded_len);curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, discardfunc); curl_easy_setopt(curlhandle,CURLOPT_READFUNCTION, readfunc);curl_easy_setopt(curlhandle, CURLOPT_READDATA, f);curl_easy_setopt(curlhandle, CURLOPT_FTPPORT, "-"); /* disable passive mode */ curl_easy_setopt(curlhandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);for (c = 0; (r != CURLE_OK) && (c < tries); c++) { /* are we resuming? */ if (c) { /* yes *//* determine the length of the file already written *//* * With NOBODY and NOHEADER, libcurl will issue a SIZE * command, but the only way to retrieve the result is * to parse the returned Content-Length header. Thus, * getcontentlengthfunc(). We need discardfunc() above* because HEADER will dump the headers to stdout* without it. */curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 1L);curl_easy_setopt(curlhandle, CURLOPT_HEADER, 1L);r = curl_easy_perform(curlhandle); if (r != CURLE_OK) continue;curl_easy_setopt(curlhandle, CURLOPT_NOBODY, 0L);curl_easy_setopt(curlhandle, CURLOPT_HEADER, 0L); fseek(f, uploaded_len, SEEK_SET);curl_easy_setopt(curlhandle, CURLOPT_APPEND,1L); } else { /* no */curl_easy_setopt(curlhandle, CURLOPT_APPEND,0L); } r =curl_easy_perform(curlhandle); } fclose(f);if (r == CURLE_OK) return 1; else{ fprintf(stderr, "%s\n", curl_easy_strerror(r));return 0; } } // 下载int download(CURL*curlhandle, const char * remotepath, const char * localpath, long timeout, long tries) { FILE *f; curl_off_t local_file_len = -1 ; long filesize =0 ; CURLcode r = CURLE_GOT_NOTHING; struct stat file_info;int use_resume = 0; //获取本地文件大小信息if(stat(localpath, &file_info) == 0){ local_file_len = file_info.st_size;use_resume = 1; } //追加方式打开文件,实现断点续传 f = fopen(localpath, "ab+"); if (f == NULL) { perror(NULL); return 0; }curl_easy_setopt(curlhandle, CURLOPT_URL, remotepath); curl_easy_setopt(curlhandle, CURLOPT_USERPWD, "spider:spider"); //连接超时设置curl_easy_setopt(curlhandle,CURLOPT_CONNECTTIMEOUT, timeout); //设置头处理函数curl_easy_setopt(curlhandle,CURLOPT_HEADERFUNCTION, getcontentlengthfunc);curl_easy_setopt(curlhandle, CURLOPT_HEADERDATA,&filesize); // 设置断点续传curl_easy_setopt(curlhandle,CURLOPT_RESUME_FROM_LARGE,use_resume?local_file_len:0);curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, writefunc); curl_easy_setopt(curlhandle,CURLOPT_WRITEDATA, f);curl_easy_setopt(curlhandle, CURLOPT_NOPROGRESS, 1L); curl_easy_setopt(curlhandle, CURLOPT_VERBOSE, 1L);r = curl_easy_perform(curlhandle); fclose(f); if (r == CURLE_OK) return 1; else{ fprintf(stderr, "%s\n", curl_easy_strerror(r)); return 0; } } int main(int c, char **argv){ CURL *curlhandle = NULL; CURL *curldwn = NULL; curl_global_init(CURL_GLOBAL_ALL); curlhandle = curl_easy_init(); curldwn = curl_easy_init(); upload(curlhandle, "ftp://192.168.0.185/a/success", "D:/abc.jpg", 1, 3); download(curldwn, "ftp://192.168.0.185/a/success", "D:/abc1.jpg", 1, 3); curl_easy_cleanup(curlhandle);curl_easy_cleanup(curldwn); curl_global_cleanup(); return 0; }。
AS400的FTPFTP是基于客户-服务器模型而设计的。
客户和服务器之间利用TCP直接连接。
与其它客户-服务器模型不同的是:FTP客户与服务器之间是要建立双重连接:一个是控制连接,一个是数据连接。
建立双重连接的原因在于FTP是一个交互会话系统,某客户每次调用FTP,便与服务器建立一个会话,会话以控制连接来维持,直到退出FTP。
控制连接负责传输控制信息,尤其是客户客户命令(比如文件传输命令等等)。
利用控制命令,客户可以向服务器提出无数次的请求(一个客户命令就是一个请求)。
客户每提出一个请求,服务器再与客户建立一个数据连接,进行实际的数据(比如文件)传输。
一旦数据传输完成,数据连接会话就被撤销,但控制连接依然存在,客户可以继续发出命令。
直到牢记键入CLOSE命令撤销控制连接,再键入QUIT退出FTP 会话。
此时双方控制进程就不再存在了。
FTP连接的建立在一个FTP会话中,需要建立一个控制连接和若干个数据连接。
建立控制连接的过程大家都很熟悉。
FTP服务器的公认端口是21。
客户控制进程申请一个随机分配的本地端口后,用常规的方法可以与服务器端口21建立一个连接。
数据连接的建立就没有那么简单了。
在建立数据连接的过程中,客户控制进程反客为主,成为连接的接收者,而服务器数据传输进程成了连接的请求者。
作为一个新的子进程,服务器传输进程可以申请一个新的端口号来建立自己的相关连接(一般是利用FTP的保留端口号20),而它向哪个客户端口发送连接请求呢?要知道客户是没有公认端口的,这时就要利用到控制连接,客户控制进程通过控制连接告知服务器进程自己的数据连接端口号,服务器控制进程将它转告自己的数据传输进程,服务器数据传输进程便可以利用它与客户建立数据连接。
FTP命令集或者“*SYSCMD”:用户可以在FTP模式中执行本地AS/400的命令。
在实际工作中,这一命令非常有用,你不用退出FTP模式就可以直接执行本地AS/400的命令。
矿产资源开发利用方案编写内容要求及审查大纲
矿产资源开发利用方案编写内容要求及《矿产资源开发利用方案》审查大纲一、概述
㈠矿区位置、隶属关系和企业性质。
如为改扩建矿山, 应说明矿山现状、
特点及存在的主要问题。
㈡编制依据
(1简述项目前期工作进展情况及与有关方面对项目的意向性协议情况。
(2 列出开发利用方案编制所依据的主要基础性资料的名称。
如经储量管理部门认定的矿区地质勘探报告、选矿试验报告、加工利用试验报告、工程地质初评资料、矿区水文资料和供水资料等。
对改、扩建矿山应有生产实际资料, 如矿山总平面现状图、矿床开拓系统图、采场现状图和主要采选设备清单等。
二、矿产品需求现状和预测
㈠该矿产在国内需求情况和市场供应情况
1、矿产品现状及加工利用趋向。
2、国内近、远期的需求量及主要销向预测。
㈡产品价格分析
1、国内矿产品价格现状。
2、矿产品价格稳定性及变化趋势。
三、矿产资源概况
㈠矿区总体概况
1、矿区总体规划情况。
2、矿区矿产资源概况。
3、该设计与矿区总体开发的关系。
㈡该设计项目的资源概况
1、矿床地质及构造特征。
2、矿床开采技术条件及水文地质条件。