
LINUX学习—FTP云服务器
发布日期:2021-05-10 23:57:41
浏览次数:8
分类:精选文章
本文共 5933 字,大约阅读时间需要 19 分钟。
FTP服务器
通过之前的socket协议学习我们了解到服务器与客户端的工作方式,服务器可以接受多台客户端
Sever.c
#include#include #include #include #include #include #include #include #include #include #include "config.h"int option_cmd(char *cmd){ if(!(strcmp("ls",cmd)))//若输入的cmd与ls相等则返回LS { return LS;} if(!(strcmp("pwd",cmd))) { return PWD;} if(!(strcmp("quit",cmd))) { return QUIT;} if(strstr(cmd,"cd") != NULL)//例如输入"cd config.h" "cd"是该字符串的子串则返回CD { return CD;} if(strstr(cmd,"get") != NULL) { return GET;} if(strstr(cmd,"put") != NULL) { return PUT;}}//对字符串进行处理char *GetDir(char *dircmd){ char *p; p = strtok(dircmd,"");//以空格为分隔,分割指令字符串 p = strtok(NULL,""); return p; }void command(struct Message msg,int fd){ char cmdbuf[1024] = { 0};//定义缓冲区 char *file = NULL; int file_fd; printf("the client cmd is:%s\n",msg.data); int cmd = option_cmd(msg.data);//调用函数将字符串指令转换成整数 switch(cmd) { case LS://显示所有文件 case PWD: msg.type = 0; FILE *p = popen(msg.data,"r"); fread(msg.data,sizeof(msg.data),1,p); write(fd,&msg,sizeof(msg)); break; case QUIT://退出本次连接 printf("the client die out\n"); exit(-1); case CD: //进入文件夹 msg.type = 1; char *dir = GetDir(msg.data);//分割命令字符串 printf("the dir is: %s\n",dir); case PUT://上传文件 file_fd = open(GetDir(msg.data),O_CREAT|O_RDWR,0666); write(file_fd,msg.msgbuf,strlen(msg.msgbuf)); close(file_fd); break; case GET://获取文件 file = GetDir(msg.data); if(access(file,F_OK) == -1) { strcpy(msg.data,"the file don't exit"); write(fd,&msg,sizeof(msg)); } else { msg.type = DOFILE; file_fd = open(file,O_RDWR); read(file_fd,cmdbuf,sizeof(cmdbuf)); close(file_fd); strcpy(msg.data,cmdbuf);//将缓冲区中的字符串拷贝到结构体数组中 write(fd,&msg,sizeof(msg));//将数据写入客户端 } break; } }int main(int argc, char **argv){ int s_fd;// int c_fd; int nread;//定义读数据的大小 int i; struct Message msg;//定义Message对象 struct sockaddr_in s_addr;//定义两个结构体对象 struct sockaddr_in c_addr; memset(&s_addr, 0, sizeof(struct sockaddr_in));//初始化结构体对象 memset(&c_addr, 0, sizeof(struct sockaddr_in)); int len = sizeof(struct sockaddr_in);//定义变量,代替结构体长度 //1.socket s_fd = socket(AF_INET, SOCK_STREAM, 0);//创建服务端套接字对象 if(s_fd == -1) { perror("socket error:"); exit(-1); }//判断是否建立成功 //2.bind将服务器与客户端的IP端口号绑定起来 s_addr.sin_family = AF_INET;//使用IPv4通信方式 s_addr.sin_port = htons(atoi(argv[2]));//将命令行参数转换成整数形式 inet_aton(argv[1],&s_addr.sin_addr);//将字符串IP转换为32位的网络地址IP if(bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)) == -1) { perror("bind error: "); exit(-1); }//判断绑定是否成功 //3.listen listen(s_fd, 10);//监听是否有客户端接入,设置最大接入数量10 //4.accept while(1)//设置死循环不断接受来自客户端的指令 { c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&len); if(c_fd == -1) { printf("accept client failed\n"); perror("why error:"); exit(-1); } printf("IP address:\n",inet_ntoa(c_addr.sin_addr)); if(fork() == 0)//接收成功后创建子进程执行客户端指令 { printf("the client connect success:\n"); nread = read(c_fd,&msg,sizeof(msg.data)); if(nread == 0)//客户端没有输入 { printf("no input\n"); break; } else if( nread == -1)//创建子进程错误 { printf("error\n"); exit(-1); } else if( nread >0 ) { command(msg,c_fd);//调用函数实现对指令处理 } } } close(c_fd); close(s_fd);//关闭两个文件 return 0;}
Client.c
#include#include #include #include #include #include #include #include #include #include #include "config.h"int option_cmd(char *cmd){ if( !(strcmp("ls",cmd)) ) return LS; if( !(strcmp("pwd",cmd)) ) return PWD; if( !(strcmp("lls",cmd)) ) return LLS; if( !(strcmp("quit",cmd)) ) return QUIT; if( strstr(cmd,"get") ) return GET; if( strstr(cmd,"put") ) return PUT; if( !(strcmp("cd",cmd)) ) return CD; if( strstr(cmd,"lcd")) return LCD; return -1;}char *GetDir(char *cmd)//对字符串进行分割{ char *p; p = strtok(cmd," "); p = strtok(NULL,""); if( p == NULL) { return cmd; } return p;}int option_cmd_handle(struct Message msg,int fd){ char *dir = NULL; char buf[128] = { '\0'}; char cmdbuf[1024]; int CMD; int file_fd; strcpy(buf,msg.data);//将输入的命令放到buf缓冲区 dir = GetDir(buf);//对字符串进行分割处理 CMD = option_cmd(buf);//命令分类 switch(CMD) { case LS: case PWD: msg.type = 0; write(fd,&msg,sizeof(msg)); break; case CD: msg.type = 1; write(fd,&msg,sizeof(msg)); break; case LCD: chdir(dir);//打开分割后的命令 break; case QUIT: strcpy(msg.data,"quit");//终止命令拷贝 write(fd,&msg,sizeof(msg));//发送数据 close(fd);//关闭文件 exit(-1); case LLS: system("ls");//调用系统函数LS查看所有文件 break; case GET: write(fd,&msg,sizeof(msg)); break; case PUT: strcpy(cmdbuf,msg.data);//复制指令 if(access(dir,F_OK) == -1)//查看是否有这个文件 { printf("the %s file is no have\n",dir); } else { file_fd = open(dir,O_RDWR); read(file_fd,msg.msgbuf,sizeof(msg.msgbuf)); close(file_fd); write(fd,&msg,sizeof(msg)); } break; } return CMD;}void message_handle(struct Message msg,int fd)//建立连接后对指令进行打印{ int nread; int newfile_fd; struct Message M; nread = read(fd,&M,sizeof(M)); if(nread == 0) { printf("the server die out!\n"); exit(-1); } else if(M.type == DOFILE) { char *file = GetDir(msg.data);//字符串分割 fflush(stdout); } else { printf("%s\n",M.data); fflush(stdout); }}int main(int argc, char **argv){ int c_fd; int n_read; struct Message msg;//定义Message结构体对象 //1.socket c_fd = socket(AF_INET,SOCK_STREAM,0);//建立客户端套接字对象 if(c_fd == -1) { printf("create socket failed\n"); exit(-1); }//判断是否建立成功 struct sockaddr_in c_addr; memset(&c_addr,0,sizeof(struct sockaddr_in));//初始化结构体对象 c_addr.sin_family = AF_INET; c_addr.sin_port = htons(atoi(argv[2])); inet_aton(argv[1],&c_addr.sin_addr); //2.connect与服务器建立连接 if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1)//判断建立连接是否成功 { printf("connect server port failed\n"); exit(-1); } else { printf("connect sever ok!\n"); } while(1)//连接成功后输入字符串指令 { memset(msg.data,0,sizeof(msg.data));//初始化 gets(msg.data); printf("you scanf cmd is: %s\n",msg.data); int cmd = option_cmd_handle(msg,c_fd);//对字符串进行处理 if(cmd > IFGO) { fflush(stdout);//强迫将缓冲区内的数据写回参数stream 指定的文件中 continue; } message_handle(msg,c_fd);//调用函数对命令进行打印 } return 0;}
本文章仅用于学习记录,若存在问题将会后续改正
发表评论
最新留言
做的很好,不错不错
[***.243.131.199]2025年04月05日 22时32分17秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
基于Laravel5.8开发的高性能后台开发框架
2021-05-11
SpringCloud使用Gateway构建微服务网关
2021-05-11
SpringBoot+Vue+ElementUI低代码前后端分离后台管理系统
2021-05-11
基于Laravel8.x+Vue+AntDesign社会团购后台管理系统源码
2021-05-11
springboot(9)——员工管理系统之登录功能的实现
2021-05-11
请你谈谈Redis主从复制的理解?
2021-05-11
请你谈谈Redis缓存穿透和雪崩?
2021-05-11
请你谈谈http状态码、http 请求包含哪几个部分?
2021-05-11
方法的重载
2021-05-11
链表面试题(7)
2021-05-11
寻找第K大
2021-05-11
【ES6(2015)】Object对象
2021-05-11
【ES6(2015)】RegExp
2021-05-11
linux服务器系统的介绍----初学者
2021-05-11
2年经验大专生,拿下阿里有多难?(已拿offer,附上面经)
2021-05-11
从需求出发:QMUI 最新版 QMUISchemeHandler 的设计与实现解析
2021-05-11
浅谈持续集成(CI)、持续交付(CD)、持续部署(CD)
2021-05-11
成为一个优秀的测试工程师需要具备哪些知识和经验?
2021-05-11
深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
2021-05-11
HDU4814——数学,模拟进制转换
2021-05-11