项目功能
一、服务端
1.定义命令宏
2.命令转换
3.服务端的网络编程
4.实现LS,PWD功能
5.实现GET功能
6.实现PUT功能
7.实现CD,QUIT功能
二、客户端
1.实现LS,PWD,CD,GET功能
2.实现PUT功能
3.实现LLS,LCD,QUIT功能
4.打印服务端的数据
三.整体项目代码

一、服务端
1.定义命令宏
首先我们先创建一个config.h文件,用于存放我们将要输入的命令

#define LS      0
#define PWD     1
#define GET     2#define IFGO    3#define LLS     4
#define LCD     5
#define CD      6
#define PUT     7
#define QUIT    8
#define DOFILE  9struct Msg {int type;char data[1024];        //存放命令和文件数据char secondbuf[1024];   //存放文件内容
};

2.命令转换
定义一个函数将我们输入的命令转换为我们定义的宏

int get_cmd_type(char *cmd)
{/* strcmp(s1,s1)比较 s1 和 s2 若s1=s2,返回0*//*strstr(s1,s1)在字符串 s1 中查找第一次出现字符串 s2 的位置,未找到返回NULL*/if(strcmp(cmd, "ls") == 0)        return LS;if(strcmp(cmd, "pwd") == 0)       return PWD;if(strcmp(cmd, "quit") == 0)      return QUIT;if(strstr(cmd, "get") != NULL)    return GET;if(strstr(cmd, "put")!= NULL)     return PUT;if(strstr(cmd, "cd")!= NULL)      return CD;return 250;
}

3.服务端的网络编程
步骤:socket—bind—listen—while(1){accept—fork—while(1)—read—fun}—close

int main(int argc, char **argv)
{int ss_fd;int cc_fd;int n_read;struct Msg msg;struct sockaddr_in ss_addr;struct sockaddr_in cc_addr;if(argc != 3 ){printf("Input params error!\n");exit(-1);}memset(&ss_addr, 0, sizeof(ss_addr));memset(&cc_addr, 0, sizeof(cc_addr));/* 1.socket创建网络套接字*/ss_fd = socket(AF_INET, SOCK_STREAM, 0);if(ss_fd == -1){perror("socket error!");exit(-1);}/* 2.bind设置IP地址和端口号*/ss_addr.sin_family = AF_INET;               //网络协议设置为IPV4ss_addr.sin_port = htons(atoi(argv[2]));    //传递端口号, htons:从主机(小端)到网络(大端)inet_aton(argv[1], &ss_addr.sin_addr);      //传递IP地址int ret = bind(ss_fd,(struct sockaddr *)&ss_addr, sizeof(struct sockaddr_in));if(ret == -1){perror("bind error!");exit(-1);}/* 3.listen*/listen(ss_fd, 5);/* 4.accept监听客户端请求*/int clen = sizeof(struct sockaddr_in);while(1) {cc_fd = accept(ss_fd, (struct sockaddr *)&cc_addr, &clen);if(cc_fd ==-1 ){perror("accept error!");exit(-1);}printf("get accept: %s\n", inet_ntoa(ss_addr.sin_addr));  //网络字节写转换为字符串形式,打印出IP地址/* 5.创建子进程*/if(fork() == 0){while(1){/* 清空msg当中的数据*/memset(&msg.data, 0, sizeof(msg.data));/* 1.读取cc_fd当中的数据到msg*/n_read = read(cc_fd, &msg, sizeof(msg));printf("n_read: %d\n", n_read);if(n_read == 0){printf("client out!\n");exit(-1);}/* 2.将调用msg_handler函数处理msg当中的命令数据*/if(n_read > 0){msg_handler(msg, cc_fd);}}}}return 0;
}

4.实现LS,PWD功能
当客户端输入“ls”,“pwd”指令时,需要将服务端的文件和路径显示在客户端上,那么在这里我们可以调用popen函数,该函数的功能是执行对应指令(ls,pwd),然后将结果值返回,最后可以用fread将返回值读取出来,代码如下:

case LS:
case PWD: /* 使用popen调用命令,将输出的结果存放到p中* 再使用fread,读取p中的内容*/p = popen(msg.data, "r");fread(msg.data, sizeof(msg.data), 1, p);write(cc_fd, &msg, sizeof(msg));

5.实现GET功能
当客户端输入“get”时,要获取服务端上某个文件的内容,即将服务端的文件复制到客户端上。类似于“cp”指令。代码如下:

 case GET: /* 1.获取命令需要操作的文件名*/filename = getDesDir(msg.data);/* 2.判断文件是否存在*/if(access(filename,F_OK) == -1){// printf("NO This file!\n");strcpy(msg.data,"NO This file!");write(cc_fd, &msg, sizeof(msg));}/* 3.open文件,read文件, write文件内容到cc_fd当中*/else{msg.type = DOFILE;fdfile = open(filename, O_RDWR);read(fdfile, databuf, sizeof(databuf));strcpy(msg.data,databuf);write(cc_fd, &msg, sizeof(msg));close(fdfile);}break;

比如输入“get pro.c”首先要判断获取的pro.c文件是否存在,这里就需要先创建一个能获取文件名的函数getDesDir,若文件存在,将文件中的内存写入管道中。 getDesDir代码如下:

char *getDesDir(char *data)
{char *p;p = strtok(data," ");p = strtok(NULL," ");return p;
}

6.实现PUT功能
将客户端的文件复制到服务端上。首先调用getDesDir获取文件名,然后open创建并赋予权限,然后向文件写入内容。代码如下:

 case PUT: /* 1.创建目标文件*/filename = getDesDir(msg.data);fdfile = open(filename, O_RDWR | O_CREAT, 0666);/* 2.将内容写进目标文件*/write(fdfile, msg.secondbuf, strlen(msg.secondbuf));close(fdfile);break;

7.实现CD,QUIT功能

case CD: /* 1.获取文件名*/filename = getDesDir(msg.data);/* 2.改变目录*/chdir(filename);break;case QUIT:printf("client quit\n");exit(-1);        break;

二、客户端
客户端实现的逻辑与服务端大同小异

1.实现LS,PWD,CD,GET功能
这4个指令在客户端的内容都一样,只需发送指令即可

case LS:case PWD:case CD:case GET:write(cc_fd, &msg, sizeof(msg));break;

2.实现PUT功能
首先判断需要PUT的文件是否存在,然后open,read,write,close文件即可。

case PUT:/* 1.提取目标文件名*/filename = getfilename(msg.data);/* 2.判断目标文件是否存在*/if(access(filename, F_OK) == -1){printf("NO This File!\n");                   }else{/* 3.传输文件内容,open, read, write,close*/fdfile = open(filename, O_RDWR);read(fdfile, msg.secondbuf, sizeof(msg.secondbuf));write(cc_fd, &msg, sizeof(msg));close(fdfile);}break;

3.实现LLS,LCD,QUIT功能

case LLS:system("ls");break;case LCD:/* 1.提取目标文件名*/filename = getfilename(msg.data);if(access(filename, F_OK) == -1){printf("NO This File!\n"); }else{/* 2.chdir*/chdir(filename);}break;case QUIT:write(cc_fd, &msg, sizeof(msg));close(cc_fd);exit(-1);break;

4.打印服务端的数据
1.将管道中的数据读到struct Msg结构体当中
2.GET命令比较特殊,相当于cp指令,需要open创建一个新文件,然后将数据写入到新文件当中
3.打印管道中的数据

具体功能实现代码如下:

void cmd_server_message(struct Msg msg, int cc_fd)
{int n_read;char *filename;int newfilefd;struct Msg msgget;/* 将管道中的数据读到结构体msgget中*/n_read = read(cc_fd, &msgget, sizeof(msgget));if(n_read == -1) {perror("read error!\n");;exit(-1);}if(msgget.type == DOFILE){/* 1.获取文件名*/filename = getfilename(msg.data);/* 2.创建文件*/newfilefd = open(filename, O_RDWR | O_CREAT ,0600);/* 3.将内容写入文件*/write(newfilefd, msgget.data, strlen(msgget.data));close(newfilefd);fflush(stdout);}else{/* 输出管道中的数据*/printf("------------------------\n");printf("%s\n",msgget.data);printf("------------------------\n");fflush(stdout);}}```三.整体项目代码
服务端——Server.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include “config.h”

int get_cmd_type(char cmd)
{
/
strcmp(s1,s1)比较 s1 和 s2
若s1=s2,返回0*/

/*strstr(s1,s1)在字符串 s1 中
查找第一次出现字符串 s2 的位置,未找到返回NULL*/if(strcmp(cmd, "ls") == 0)        return LS;
if(strcmp(cmd, "pwd") == 0)       return PWD;
if(strcmp(cmd, "quit") == 0)      return QUIT;if(strstr(cmd, "get") != NULL)    return GET;
if(strstr(cmd, "put")!= NULL)     return PUT;
if(strstr(cmd, "cd")!= NULL)      return CD;return 250;

}

char *getDesDir(char *data)
{
char *p;
p = strtok(data," “);
p = strtok(NULL,” ");
return p;
}

void msg_handler(struct Msg msg, int cc_fd)
{
int ret;
int fdfile;
char *filename;
FILE *p;
char databuf[1024] = {0};

/* 1.获取命令msg.data,并将数据转换为int整数类型*/
ret = get_cmd_type(msg.data);
printf("cmd: %s\n", msg.data);
printf("ret: %d\n", ret);/* 2.调用switch处理命令*/
switch(ret) {   case LS: case PWD: /* 使用popen调用命令,将输出的结果存放到p中* 再使用fread,读取p中的内容*/p = popen(msg.data, "r");fread(msg.data, sizeof(msg.data), 1, p);write(cc_fd, &msg, sizeof(msg));break;case GET: /* 1.获取命令需要操作的文件名*/filename = getDesDir(msg.data);/* 2.判断文件是否存在*/if(access(filename,F_OK) == -1){// printf("NO This file!\n");strcpy(msg.data,"NO This file!");write(cc_fd, &msg, sizeof(msg));}/* 3.open文件,read文件, write文件内容到cc_fd当中*/else{msg.type = DOFILE;fdfile = open(filename, O_RDWR);read(fdfile, databuf, sizeof(databuf));strcpy(msg.data,databuf);write(cc_fd, &msg, sizeof(msg));close(fdfile);}break;case PUT: /* 1.创建目标文件*/filename = getDesDir(msg.data);fdfile = open(filename, O_RDWR | O_CREAT, 0666);/* 2.将内容写进目标文件*/write(fdfile, msg.secondbuf, strlen(msg.secondbuf));close(fdfile);break;case CD: /* 1.获取文件名*/filename = getDesDir(msg.data);/* 2.改变目录*/chdir(filename);break;case QUIT:printf("client quit\n");exit(-1);        break;}

// printf(“sssssssssss\n”);
}

int main(int argc, char **argv)
{
int ss_fd;
int cc_fd;
int n_read;
struct Msg msg;
struct sockaddr_in ss_addr;
struct sockaddr_in cc_addr;

if(argc != 3 ){printf("Input params error!\n");exit(-1);
}memset(&ss_addr, 0, sizeof(ss_addr));
memset(&cc_addr, 0, sizeof(cc_addr));
/* 1.socket创建网络套接字*/
ss_fd = socket(AF_INET, SOCK_STREAM, 0);
if(ss_fd == -1){perror("socket error!");exit(-1);
}
/* 2.bind设置IP地址和端口号*/
ss_addr.sin_family = AF_INET;               //网络协议设置为IPV4
ss_addr.sin_port = htons(atoi(argv[2]));    //传递端口号, htons:从主机(小端)到网络(大端)
inet_aton(argv[1], &ss_addr.sin_addr);      //传递IP地址int ret = bind(ss_fd,(struct sockaddr *)&ss_addr, sizeof(struct sockaddr_in));
if(ret == -1){perror("bind error!");exit(-1);
}
/* 3.listen*/
listen(ss_fd, 5);
/* 4.accept监听客户端请求*/
int clen = sizeof(struct sockaddr_in);
while(1) {cc_fd = accept(ss_fd, (struct sockaddr *)&cc_addr, &clen);if(cc_fd ==-1 ){perror("accept error!");exit(-1);}printf("get accept: %s\n", inet_ntoa(ss_addr.sin_addr));  //网络字节写转换为字符串形式,打印出IP地址/* 5.创建子进程*/if(fork() == 0){while(1){/* 清空msg当中的数据*/memset(&msg.data, 0, sizeof(msg.data));/* 1.读取cc_fd当中的数据到msg*/n_read = read(cc_fd, &msg, sizeof(msg));printf("n_read: %d\n", n_read);if(n_read == 0){printf("client out!\n");exit(-1);}/* 2.将调用msg_handler函数处理msg当中的命令数据*/if(n_read > 0){msg_handler(msg, cc_fd);}}}
}
return 0;

}

客户端——Client.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <pthread.h>
#include <sys/socket.h>
//#include <linux/in.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include “config.h”

int cmd_int(char cmd)
{
/
strcmp(s1,s1)比较 s1 和 s2
若s1=s2,返回0*/

/*strstr(s1,s1)在字符串 s1 中
查找第一次出现字符串 s2 的位置,未找到返回NULL*/if(strcmp(cmd, "ls") == 0)        return LS;
if(strcmp(cmd, "lls") == 0)       return LLS;
if(strcmp(cmd, "pwd") == 0)       return PWD;
if(strcmp(cmd, "quit") == 0)      return QUIT;if(strstr(cmd, "get") != NULL)    return GET;
if(strstr(cmd, "put")!= NULL)     return PUT;
if(strstr(cmd, "cd")!= NULL)      return CD;
if(strstr(cmd, "lcd")!= NULL)     return LCD;

return -1;
}

char *getfilename(char *str)
{
char *filename;
filename = strtok(str, " ");
filename = strtok(NULL, " ");

return filename;

}

int cmd_handler(struct Msg msg, int cc_fd)
{
int ret;
char filename;
int fdfile;
/
1.将字符串指令,转换为int整数类型*/
ret = cmd_int(msg.data);
printf(“ret: %d\n”, ret);

/* 2.调用switch处理ret*/
switch(ret) {case LS:case PWD:case CD:case GET:write(cc_fd, &msg, sizeof(msg));break;case PUT:/* 1.提取目标文件名*/filename = getfilename(msg.data);/* 2.判断目标文件是否存在*/if(access(filename, F_OK) == -1){printf("NO This File!\n");                   }else{/* 3.传输文件内容,open, read, write,close*/fdfile = open(filename, O_RDWR);read(fdfile, msg.secondbuf, sizeof(msg.secondbuf));write(cc_fd, &msg, sizeof(msg));close(fdfile);}break;case LLS:system("ls");break;case LCD:/* 1.提取目标文件名*/filename = getfilename(msg.data);if(access(filename, F_OK) == -1){printf("NO This File!\n"); }else{/* 2.chdir*/chdir(filename);}break;case QUIT:write(cc_fd, &msg, sizeof(msg));close(cc_fd);exit(-1);break;
}return ret;

}

void cmd_server_message(struct Msg msg, int cc_fd)
{
int n_read;
char *filename;
int newfilefd;
struct Msg msgget;

/* 将管道中的数据读到结构体msgget中*/
n_read = read(cc_fd, &msgget, sizeof(msgget));if(n_read == -1) {perror("read error!\n");;exit(-1);
}if(msgget.type == DOFILE){/* 1.获取文件名*/filename = getfilename(msg.data);/* 2.创建文件*/newfilefd = open(filename, O_RDWR | O_CREAT ,0600);/* 3.将内容写入文件*/write(newfilefd, msgget.data, strlen(msgget.data));close(newfilefd);fflush(stdout);
}else{/* 输出管道中的数据*/printf("------------------------\n");printf("%s\n",msgget.data);printf("------------------------\n");fflush(stdout);
}

}

int main(int argc, char **argv)
{
int cc_fd;
int con;
int ret;
struct Msg msg;
struct sockaddr_in cc_addr;

if(argc != 3){printf("Input params error!\n");exit(-1);
}
/* 1.socket调用套接字*/
cc_fd = socket(AF_INET, SOCK_STREAM, 0);
if(cc_fd == -1) {perror("socket error");exit(-1);
}

//int connect(int sockfd, const struct sockaddr addr,
// socklen_t addrlen);
/
2.connect请求链接到服务端*/
cc_addr.sin_family = AF_INET; //网络协议设置为IPV4
cc_addr.sin_port = htons(atoi(argv[2])); //传递端口号, htons:从主机(小端)到网络(大端)
inet_aton(argv[1], &cc_addr.sin_addr); //传递IP地址

con = connect(cc_fd, (struct sockaddr *)&cc_addr, sizeof(struct sockaddr_in));
if(con == -1) {perror("connect error");exit(-1);
}
printf("connect ...\n");while(1) {/* 1.刷新msg.data*/memset(&msg.data, 0, sizeof(msg.data));/* 2.获取输入指令,保存到msg.data*/gets(msg.data);/* 3.调用cmd_handler函数,将指令传入到cc_fd中*/ret = cmd_handler(msg, cc_fd);printf("mainret:%d\n",ret);/* 4.过滤指令*/if(ret > IFGO){continue;       //跳出循环,不继续执行下面代码}if(ret == -1){printf("command error! Please enter again!\n");continue;}/* 5.输出指令产生的内容*/cmd_server_message(msg, cc_fd);
}return 0;

}


基于Linux的FTP文件传输项目(类似百度云)相关推荐

  1. Qt网络编程小项目-基于Tcp协议的文件传输项目

    目录 项目描述 Qt下Tcp服务器端和客户端流程: 具体流程: 客户端: 服务器端: 源码: 服务器端: 服务器头文件: 服务器源文件: 服务器端ui 客户端: 客户端头文件: 客户端源文件: 客户端 ...

  2. FTP文件传输协议(实现windows与linux文件互传)

    FTP文件传输协议(实现windows与linux文件互传) 目录 FTP文件传输协议(实现windows与linux文件互传) 一.FTP概述 二.FTP通信端口 三.FTP数据连接 四.FTP连接 ...

  3. Linux下基于TCP的简易文件传输(socket编程)

    Linux下基于TCP的简易文件传输(socket编程) OSI和TCP/IP: 关于TCP/IP协议 关于TCP协议 TCP编程的一般步骤[^2] TCP文件传输实现 功能概述 服务器编程 客户端编 ...

  4. 基于python的文件传输程序_7个步骤,教你快速学会用python实现ftp文件传输功能(收藏了)...

    文章主要为大家详细介绍了python实现ftp文件传输功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下!!! 本文实例为大家分享了python实现ftp文件传输的具体 ...

  5. linux做完sftp端口分离后ftp,Linux 中实现文件传输服务(FTP、SFTP)

    ????本文将介绍如何在Linux中实现文件传输,这里主要使用FTP.SFTP. ????FTP ????废话少说,直接进入正题,需要注意,FTP采用Client/Server架构,并且有两个信道(控 ...

  6. Linux 网络服务之FTP 文件传输

    Linux FTP 文件传输 --王宇然qq:496488051 实验一:配置匿名上传FTP 1.软件包安装: [root@localhost ~]# cd /misc/cd/Server       ...

  7. put与mput_常用的ftp文件传输命令为:bin、asc、put、get、mput、mget、prompt、bye。-智慧树Linux操作系统章节答案...

    Linux操作系统:常用的ftp文件传输命令为:bin.asc.put.get.mput.mget.prompt.bye.[?????] A:错 B:对 Linux操作系统章节测试答案: 对 更多相关 ...

  8. Linux运维系列总结-Linux系统启动过程、WEB工作原理、DHCP工作原理、DNS解析原理、NFS网络文件系统、FTP文件传输协议、PXE+KICKSTART自动安装系统

    Linux运维系列总结-Linux系统启动过程.WEB工作原理.DHCP工作原理.DNS解析原理.NFS网络文件系统.FTP文件传输协议.PXE+KICKSTART自动安装系统 1.Linux系统的启 ...

  9. Linux利用FTP服务传输文件(山有木兮木有枝,心悦君兮君不知)

    文章目录 一.FTP协议 二.Linux系统配置FTP协议实现文件传输 实例1:匿名用户 实例2:本地用户访问 一.FTP协议 1.FTP协议简介 与大多数 Internet服务一样,FTP也是一个c ...

  10. 详解“FTP文件传输服务”安装配置实例

    "FTP文件传输服务"安装配置实例 家住海边喜欢浪:zhang789.blog.51cto.com 目录 简介 ftp工作原理 常见的FTP服务 Vsftpd服务器的安装 Vsft ...

最新文章

  1. 瘫痪17年,利用双向脑机接口来诱发触觉,控制机械手
  2. 漫谈 Weblogic CVE-2020-2555
  3. Websocket总结
  4. 什么时候html的过渡版本,CSS过渡与转换
  5. github的一些简单用法
  6. asp.net 得到上一页地址
  7. 数据结构-Hash总结(二)
  8. 前端学习(1954)vue之电商管理系统电商系统之重置表单数据
  9. php能做什么程序,PHP 能做什么?
  10. android水印的添加,Android添加水印的正确方法 只要三步!
  11. Mac上通过docker配置PHP开发环境
  12. js刻度尺插件_html5 canvas+js刻度尺代码
  13. bh1750采集流程图_基于BH1750的光照度检测)报告方案.doc
  14. spring boot 整合 ip2region(ip地址库)
  15. 狂神学习系列04:MySQL+JDBC
  16. 测试工程师也应该具备产品化思维吗?
  17. iOS 局域网通讯 MultipeerConnectivity
  18. Thymeleaf模板(全程案例详解)
  19. Java基础——狂神说
  20. Spark提交报错:1 node(s) are excluded in this operation

热门文章

  1. 【深度学习-吴恩达】L1-3 浅层神经网络 作业
  2. Android 手机遥控器控制机顶盒(电视)
  3. 【温故而知新】计算机408之计算机网络速记
  4. 技术解密之百度搜索中台低代码的探索与实践
  5. mybatis 源码系列(四) 数据库驱动Driver加载方式
  6. 详解 JavaScript 的发展史
  7. css 动画 (transition animation)
  8. WINDOWS备份与恢复
  9. firewalld的练习
  10. 转贴自圣骑士wind:Google Maps Android API V2的使用及问题解决