Linux系统编程——DIY编写Linux中的FTP(客户端与服务器)
Linux
C语言
函数,指针,结构体
Linux套接字,进程,多种输入输出函数,网络编程,底层调用
客户端程序连接到服务器后,可通过ls,lls,pwd,put等多种指令操作服务器端文件,打印文件路径,下载上传文件
// 终端1 gcc ftp_server.c -o server ./server 192.168.3.8 8000 --- // 终端2 gcc ftp_client.c -o client ./client 192.168.3.8 8000 --- //可发送指令 ls pwd lls lcd quit get xxx put xxx
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #define LS 0 #define GET 1 #define PWD 2 #define IFGO 3 #define LCD 4 #define LLS 5 #define CD 6 #define PUT 7 #define QUIT 8 #define DOFILE 9 struct Msg { int type; char data[1024]; char secondBuf[128]; }; int get_cmd_type(char *cmd) { if(!strcmp("ls",cmd)) return LS; if(!strcmp("quit",cmd)) return QUIT; if(!strcmp("pwd",cmd)) return PWD; if(strstr(cmd,"cd")!=NULL) return CD; if(strstr(cmd,"get")!=NULL) return GET; if(strstr(cmd,"put")!=NULL) return PUT; return 100; } //分割字符串 char *getDesDir(char *cmsg) { char *p; p = strtok(cmsg,""); p = strtok(NULL,""); return p; } void msg_handler(struct Msg msg,int fd) { char dataBuf[1024] = {0}; char *file = NULL; int fdfile; //msg.data为数组字符串类型 printf("cmd:%s\n",msg.data); //将字符串转换为整型数 int ret = get_cmd_type(msg.data); switch(ret) { case LS: //输出当前路径 case PWD: msg.type = 0; FILE *r = popen(msg.data,"r"); fread(msg.data, sizeof(msg.data),1,r); write(fd, &msg, sizeof(msg)); break; case CD: msg.type = 1; //分割字符串 char *dir = getDesDir(msg.data); printf("dir:%s\n",dir); chdir(dir); break; case GET: //分割字符串 file = getDesDir(msg.data); if(access(file,F_OK) == -1) { strcpy(msg.data,"No this file!"); write(fd,&msg,sizeof(msg)); } else { msg.type = DOFILE; fdfile = open(file,O_RDWR); read(fdfile,dataBuf,sizeof(dataBuf)); close(fdfile); strcpy(msg.data,dataBuf); write(fd,&msg,sizeof(msg)); } break; case PUT: fdfile = open(getDesDir(msg.data),O_RDWR|O_CREAT,0666); write(fdfile, msg.secondBuf, strlen(msg.secondBuf)); close(fdfile); break; case QUIT: printf("client quit!\n"); exit(-1); } } int main(int argc, char **argv) { int s_fd; int c_fd; int n_read; char readBuf[128]; struct sockaddr_in s_addr; struct sockaddr_in c_addr; struct Msg msg; if(argc != 3) { printf("Unqualified parameters!\n"); exit(-1); } memset(&s_addr,0,sizeof(struct sockaddr_in)); memset(&c_addr,0,sizeof(struct sockaddr_in)); //1.socket s_fd = socket(AF_INET, SOCK_STREAM, 0); if(s_fd == -1) { perror("socket"); exit(-1); } s_addr.sin_family = AF_INET; s_addr.sin_port = htons(atoi(argv[2])); inet_aton("argv[1]",&s_addr.sin_addr); //2.bind bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in)); //3.listen listen(s_fd,10); //4.accept int clen = sizeof(struct sockaddr_in); while(1) { c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen); if(c_fd == -1) perror("accept"); printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr)); //当新的客户端接入的时候才创建子进程 //一个子进程负责一条连接通道 if(fork() == 0) { while(1) { memset(msg.data,0,sizeof(msg.data)); //等待输入,将所有数据都传到msg结构体中 n_read = read(c_fd,&msg,sizeof(msg)); if(n_read == 0) { printf("client out\n"); break; } else if(n_read > 0) { msg_handler(msg,c_fd); } } } } close(c_fd); close(s_fd); return 0; }
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #define LS 0 #define GET 1 #define PWD 2 #define IFGO 3 #define LCD 4 #define LLS 5 #define CD 6 #define PUT 7 #define QUIT 8 #define DOFILE 9 struct Msg { int type; char data[1024]; char secondBuf[128]; }; char *getdir(char *cmd) { char *p; p = strtok(cmd," "); p = strtok(NULL," "); return p; } int get_cmd_type(char *cmd) { if(strstr(cmd,"lcd")) return LCD; if(!strcmp("quit",cmd)) return QUIT; if(!strcmp("ls",cmd)) return LS; if(!strcmp("lls",cmd)) return LLS; if(!strcmp("pwd",cmd)) return LS; if(strstr(cmd,"cd")) return CD; if(strstr(cmd,"get")) return GET; if(strstr(cmd,"put")) return PUT; return -1; } int cmd_handler(struct Msg msg, int fd) { char *dir = NULL; char buf[32]; int ret; int filefd; //将字符串转换为宏 ret = get_cmd_type(msg.data); switch(ret) { case LS: case CD: case PWD: msg.type = 0; //发送给宏 write(fd, &msg, sizeof(msg)); break; case GET: msg.type = 2; write(fd, &msg,sizeof(msg)); break; case PUT: strcpy(buf, msg.data); dir = getdir(buf); if(access(dir, F_OK) == -1) { printf("%s not exsit\n",dir); } else { filefd = open(dir, O_RDWR); read(filefd,msg.secondBuf,sizeof(msg.secondBuf)); close(filefd); write(fd, &msg,sizeof(msg)); } break; case LLS: system("ls"); break; case LCD: dir = getdir(msg.data); chdir(dir); break; case QUIT: strcpy(msg.data,"quit"); write(fd,&msg,sizeof(msg)); close(fd); exit(-1); } return ret; } void handler_server_message(int c_fd,struct Msg msg) { int n_read; struct Msg msgget; int newfilefd; //读取服务器数据 n_read = read(c_fd, &msgget,sizeof(msgget)); //连接断开 if(n_read == 0) { printf("server is out,quit\n"); exit(-1); } else if(msgget.type == DOFILE) { char *p = getdir(msg.data); newfilefd = open(p,O_RDWR|O_CREAT,0600); write(newfilefd,msgget.data,strlen(msgget.data)); putchar('>'); fflush(stdout); } else { printf("--------------------------------------\n"); printf("\n%s\n",msgget.data); printf("--------------------------------------\n"); putchar('>'); fflush(stdout); } } int main(int argc, char **argv) { int c_fd; struct sockaddr_in c_addr; struct Msg msg; memset(&c_addr, 0, sizeof(struct sockaddr_in)); if(argc != 3) { printf("param is not good\n"); exit(-1); } //1.socket c_fd = socket(AF_INET, SOCK_STREAM, 0); if(c_fd == -1) { perror("socket"); exit(-1); } 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) { perror("connect"); exit(-1); } printf("connect ...\n"); int mark = 0; while(1) { memset(msg.data, 0, sizeof(msg.data)); if(mark == 0) printf(">"); //接收用户输入 gets(msg.data); //规范格式 if(strlen(msg.data) == 0) { if(mark == 1) { printf(">"); } continue; } mark = 1; //调用处理 int ret = cmd_handler(msg,c_fd); if(ret >IFGO) { putchar('>'); fflush(stdout); continue; } if(ret == -1) { printf("command not \n"); printf(">"); fflush(stdout); continue; } handler_server_message(c_fd, msg); } return 0; }
如果文章有帮助就点个赞哦,有问题可留言。