代码编织梦想

一、项目介绍

1、本项目基于Linux平台,主要结构分为ftp客户端和服务端,实现的功能和Linux开源的ftp服务器类似,客戶端通过网络IP地址和端口号,远程获取服务端磁盘上的文件夹内容,支持查看服务端文件内容并下载所需文件,或者查看本地文件内容并上传文件到服务器等功能,服务端主要为接受客户端接入信息和获取操作指令。

2、 ftp服务器实现思路:通过Socket通信建立套接字,当收到客户端接入的时候,创建子进程对接连接,子进程启动后分析来自客户端的指令。比如收到get file的指令,是客户端想要获取file文件,先用strstr函数进行字符串分割,获取到文件名,再判断文件是否存在,如果文件存在,就读取文件內容,再将內容通过套接字发给客户端,客户端收到数据后,创建文件,并将收到的数据写入文件,完成文件的远程下载。

3、ftp客户端实现思路:通过Socket通信建立套接字连接服务器,连接成功进入密码的验证,密码输入正确就进入命令行的输入,将输入的命令通过函数处理来判断是否发送到服务端处理,比如输入put file的指令,是客户端想要上传file文件,直接通过套接字将输入内容完整的发送到服务端进行处理,完成文件的远程上传;如输入lls指令,是客户想查看本地目录,直接调用system函数实现即可,不用发送到服务端。

涉及技术:网络编程、文件操作、字符串运用、进程操作、数据算法。(升级版:可通过共享内存和信号量等进程间通信处理服务端和客户端的信息交互)

二、基本功能

用socket,建立起服务端与客户端的对接;支持 客户端密码验证进入ftp云盘
客户端
ls:查看服务端当前路径下的所有文件;
lls:查看客户端当前路径下的所有文件;
cd xx:服务端进入xx路径;
lcd xx:客户端进入xx路径;
pwd:查看服务端当前路径;
lpwd:查看客户端当前路径;
get xx:从服务端当前路径获取xx文件到客户端当前路径上;
put xx:将客户端当前路径xx文件发送到服务端当前路径;
cat xx: 查看服务端中文件的具体内容
cad xx: 查看客户端中文件的具体内容
rm xx: 删除客户端中的文件(可自行拓展删除服务器文件等指令要求)
quit:断开服务器端连接,退出;
服务端
1、获取接入的客户端的IP地址( 可支持多个客户端同时接入
2、不断监听客户端的指令( 接收指令,方便后台处理)。
3、在接收上面客户端的指令后,去执行指令。( 核心操作

三、代码实现

服务端:

#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include "config1.h"

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;
        if(strstr(cmd,"cat") !=NULL)   return CAT;//判断客户端发送的指令是否存在某些字符

        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 catBuf[1024] ={0};
        char *file =NULL;
        char *file1 =NULL;
        int fdfile;
        int fdcat;
        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");//调用popen运行并获取运行结果
                                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);//调用chadir改变当前目录,进入所需目录

                                break;
                        case CAT:
                                file1 =getDesdir(msg.data);

                                if(access(file1,F_OK == -1)){
                                        strcpy(msg.data,"NO This File!");
                                        write(fd,&msg,sizeof(msg));
                                    //判断查看的服务端文件是否存在
                                }else{
                                    //存在就打开它
                                        fdcat =open(file1,O_RDWR);
                                        read(fdcat,catBuf,sizeof(catBuf));//读取它
                                        close(fdcat);

                                        strcpy(msg.data,catBuf);
                                        write(fd,&msg,sizeof(msg));//写在套接字,发给客户端
                                }
                                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 Msg msg;//定义指令和数据处理结构体,在config.h头文件
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;

        if(argc !=3){

                printf("param is not good\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;//设置协议族为tcp协议
        s_addr.sin_port=htons(atoi(argv[2]));//设置端口号
        inet_aton(argv[1],&s_addr.sin_addr);//设置IP地址
        //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);/接收客户端的连接请求,返回描述符c_fd
                if(c_fd == -1){

                        perror("accept");
                }

                printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));//获取接入客户端IP地址

        //5.read
                        if(fork() ==0){
                        //有客户端接入创建子进程处理它
                        while(1){
                                memset(msg.data,0,sizeof(msg.data));
                                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;
}

客户端主函数:

int main(int argc,char **argv)
{

        int c_fd;
        char passward[16]={0};//存储密码
        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_in)) == -1){

                perror("connect");
                exit(-1);
        }
        printf("connect...\n");
        while(1){
        memset(passward,0,sizeof(passward));//清空密码
        printf("please input passward:");
        gets(passward);//密码的输入
        if((strcmp(passward, "ftp") != 0)){
                printf("passward error!!!\n");
                }
        else break;//密码正确跳出循环,错误不断提醒用户输入
        }
        printf("Welcome to zyf FTP Netdis!\n");
        printf("--------------------------------\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;//客户端自身可以实现端,eg:lls指令
                }
                if(ret ==-1){
                        printf("command not found!\n");
                        putchar('>');
                        fflush(stdout);
                        continue;
                    //指令不存在提醒
                }
                handler_server_message(c_fd,msg);//需要发送服务器处理端

        }


        return 0;
}

config1.h

#define LS   0
#define GET  1
#define PWD  2
#define CAT  3

#define IFGO 4
#define LPWD 5
#define LCD  6
#define LLS  7
#define PUT  8
#define CAD 9

#define QUIT   10
#define DOFILE 11
#define CD   12
#define RM   13


struct Msg
{

        int type;
        char data[1024];//处理指令
        char secondBuf[128];//处理数据


};

四、实现效果

ec4ee4bfb00ec44745ddfbdfd4c2e002.png
5b9513fd210dad88925d91309ad68d26.png
27cd8d5bba9ebec6cfc6c687b6a409aa.png

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_70987863/article/details/128859210

linux必备软件合集_hpulfc的博客-爱代码爱编程_linux必备100个软件

Ubuntu常用软件合集 我用的使Ubuntu-Kylin14.04,原因呢主要是觉得使本土化的,自带了日历、输入法、优客助手等易于上手的应用。也省的每次安装完原生的系统再麻烦的安装,但是这些软件并不仅仅局限于ubuntu14.04 美化篇 刚装上ubuntu,看起来很朴素,而且用起来很多习惯发生了变化,也不怎么美观,但是ubuntu因为linux强大的软

在centos搭建ftp服务-简单易学_小c的博客的博客-爱代码爱编程

1.搭建ftp服务器 利用yum安装vsftpd[root@jun-machine /]# yum install vsftpd -y 如果自己的yum源,没有改为国内镜像的话,要改,我的是使用百度云的云主机,所以默认都已经

阿里云快速入门教程_weixin_33769207的博客-爱代码爱编程

一般购买和使用云服务器 ECS 实例遵循以下步骤: 突发性实例特价,2核4G,3年仅需699:点我组队 1、配置选型 2、创建实例 3、远程连接实例 4、如果是 Linux 实例,格式化和挂载数据盘 ;如果是 Windows 实例,格式化数据盘   国际惯例,发个阿里云券:点我点我  

安全解决方案-爱代码爱编程

项目收集的思路: 一个是关注互联网企业/团队的安全开源项目,经企业内部实践,这些最佳实践值得借鉴。另一个是来自企业安全能力建设的需求,根据需求分类,如WAF、HIDS、Git监控等。 这个收集是一个长期的过程,我在GitHub创建了一个项目,专门用来收集一些优秀的甲方安全项目。 GitHub项目地址: https://github.com/Bypa

安装和使用ArchLiunx超详细教程-爱代码爱编程

安装系统 一、下载介质 https://www.archlinux.org/download/二、启动 ISO 到Live 环境 此步骤由很多种方式: 制作ISO为U盘启动工具,可以使用 Ultra ISO 或 大白菜有Linux/Unix系统的,可以硬盘写入Grub,制作启动项三、安装前的准备 启动 iso到 live 环境,登录后,在 /ro

简易搭建阿里云个人简历网站教程-爱代码爱编程

通过ecs服务器的一个实践~~~ 1. 开通云服务器(学生) 我们通过登录该链接(高校计划),登录之后根据提示进行领取ecs学生服务器。 tips 需要注意的是领取时间为每日的上午8点,数量有限(准点领取自然不成问题); 选择的区域也是不能更改的哦。 2. 安装网页运行环境 一般来说,主流的建站环境就是 LAMP 环境,它是 Lin

基于TCP协议的简易FTP云盘(服务端)-爱代码爱编程

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <stdlib.h>

基于TCP协议的简易FTP云盘(客户端)-爱代码爱编程

#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <stdlib.h>

恶意代码分析实战——远程服务器恶意程序-爱代码爱编程

QQ 1274510382 Wechat JNZ_aming 商业联盟 QQ群538250800 技术搞事 QQ群599020441 解决方案 QQ群152889761 加入我们 QQ群649347320 共享学习 QQ群674240731 纪年科技aming 网络安全 ,深度学习,嵌入式,机器强化,生物智能,生命科学。 叮叮叮:产品已上线 —>

linux 云主机 管理软件,常用6款云服务器管理软件(上)-爱代码爱编程

服务器常用Linux,往往是不具备图形化界面的,所以需要使用者精通Linux命令。非专业的运维人员使用起来有难度,不过现在很多具有图形化界面的面板帮助我们解决了这个问题。 这次我们看一下常用的6款服务器面板管理软件,希望能对您建站搭应用有所帮助。本文是上篇,讲了三个,由于篇幅问题,如果想要继续阅读下篇请参考:《常用6款云服务器管理软件(下)》 一、

【linux】简易ftp文件传输项目(云盘)_apibro的博客-爱代码爱编程

前言:这是对linux系统编程学习的总结,具体操作过程在代码里有注释。 项目功能 显示服务端文件:ls显示服务端当前工作目录:pwd切换服务端目录:cd获取服务端文件:get将客户端文件上传到服务端:put显示客户端文件

基于tcp协议的简易ftp云盘_使用tcp可以下载ftp文件么-爱代码爱编程

        这个项目分成ftp客户端及服务端,实现的功能和Linux开源的ftp服务器类似,客戶端通过网络,远程获取服务端磁盘上的文件夹内容,下载文件,上传文件等功能。(基本功能描述)         ftp服务器用到的是Socket通信,当收到客户端接入的时候,创建子进程对接连接,子进程启动后分析来自客户端的指令。比如收到get file1的指令,

【vim】c语言代码提示_vim代码提示-爱代码爱编程

前言 常见的C语言提示插件是YouCompleteMe,这个插件安装比较麻烦,在这推荐一款coc.nvim这个插件,github仓库地址:https://github.com/neoclide/coc.nvim/ 下面是

windows使用命令脚本快速修改ip地址_自动设置ip地址脚本-爱代码爱编程

一、场景 有 N 台内网工控机, 需要安装环境,发布程序,测试,调试 等等(暂不考虑部署k8s)。由于是内网, 最好的连接方式就是本机电脑和工控机组成一个局域网进行通信。然而每台电脑的ip地址又不一致(不在同网段),导致每次连接不同的工控机都需要修改本机的ip地址, 网关等信息, 很是麻烦, 于是就编写了一个简单的修改ip地址的脚本, 记录一下, 方便以