Linux FTP云盘项目

项目简介:

Linux网络编程实现的FTP服务器,服务器由服务端和客户端组成,具有浏览远程服务端的文件和浏览客户端本地文件,客户端对远程服务端文件的上传和下载。

基本功能:

ls———查看服务端文件

lls———查看客户端自己的文件

cd———切换服务端目录

lcd———切换客户端自己的目录

put———上传文件

get———下载文件

基本思路:

服务端:socket 创建服务端的套接字 2:bind 端口号和IP地址 3:listen 监听客户端的连接 4:accept 接受客户端的接 入 5:read 接收

客户端:.socket 创建客户端的套接字,构建客户端和服务端发送和接收信息的桥梁 2.connect 连接上服务端 3.获取用户键 盘输入,处理输入命令buf 4.send (write)客户端的command到服务端 5.read 服务端返回的message

服务端代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"

//分割字符串
char *getDesDir(char *msg)  
{
        char *p;
        p = strtok(msg," ");
        p = strtok(NULL," ");
        return p;
}

//把指令转化为整形数
int get_cmd_type(char *cmd)
{
    if(!strcmp("ls",cmd))         return LS;
    if(!strcmp("pwd",cmd))        return PWD;
    if(!strcmp("quit",cmd))       return QUIT;

    if(strncmp("cd",cmd,2)==0)    return CD;
    if(strncmp("get",cmd,3)==0)   return GET;
    if(strncmp("put",cmd,3)==0)   return PUT;

    return 100;
}

//处理客户端发来的指令
void msg_handler(struct Msg msg,int fd)
{
    int filefd; 
    char *filename = NULL;
    char databuf[1024] = {0};

    printf("执行命令:%s\n",msg.cmd);
    int ret = get_cmd_type(msg.cmd);

    switch(ret){
        case LS: 
        case PWD:
        {
            FILE *r = popen(msg.cmd,"r");
            fread(msg.cmd,sizeof(msg.cmd),1,r);
            write(fd,msg.cmd,sizeof(msg.cmd));
            break;
        }
        
        /*从服务器上获取指定的文件*/
        case GET:
            filename = getDesDir(msg.cmd);
            if(access(filename,F_OK) == -1){ //判断文件是否存在
                strcpy(msg.cmd,"文件不存在");
                write(fd,&msg,sizeof(msg));
            }else{   
                msg.type = DOFILE;
                filefd = open(filename,O_RDWR);
                read(filefd,databuf,sizeof(databuf));
                close(filefd);

                strcpy(msg.buf,databuf);
                write(fd,&msg,sizeof(msg));
            }
            break;
        
        /*将本地客户端上的指定文件上传到服务器*/
        case PUT:
            filefd = open(getDesDir(msg.cmd),O_RDWR|O_CREAT,0666);
            write(filefd,msg.buf,strlen(msg.buf));
            close(filefd);
            break;

        /*改变服务器上的当前工作目录*/
        case CD:
        {
            // msg.type = 1;
            char *dir = getDesDir(msg.cmd);
            printf("dir = %s\n",dir);
            chdir(dir);
            break;            
        }

        case QUIT:
            printf("服务器已退出\n");
            exit(-1);
    }
}

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

	int s_fd; 
    int c_fd;
    int n_read;
    struct sockaddr_in s_addr;
    struct sockaddr_in c_addr;
    struct Msg msg;
    

    memset(&s_addr,0,sizeof(struct sockaddr_in));
    memset(&c_addr,0,sizeof(struct sockaddr_in));

    //1.创建套接字
	s_fd = socket(AF_INET,SOCK_STREAM,0);

    //2.绑定IP地址和端口号
	s_addr.sin_family = AF_INET; //选择协议族
	s_addr.sin_port = htons(atoi(argv[2])); //绑定端口号
	inet_aton(argv[1],&s_addr.sin_addr); //将IP地址转化成网络能识别的格式	
	bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));

    //3.监听连接
	listen(s_fd,10);
    int clen = sizeof(struct sockaddr_in);    

    while (1)
    {
        //4.等待客户端连接
        c_fd = accept(s_fd,(struct sockaddr *)&c_addr,&clen);
        if(c_fd == -1){
            perror("accpet");
            exit(-1);
        }
        printf("connect = %s\n",inet_ntoa(c_addr.sin_addr));

        //5.创建子进程对接客户端
        if(fork() == 0){
            while (1)
            {
                memset(msg.cmd,0,sizeof(msg.cmd));
                //6.读取客户端发来的指令
                n_read = read(c_fd,&msg,sizeof(msg));
                if(n_read == 0){
                    printf("client quit\n");
                    break;
                }else if(n_read > 0){
                    //7.处理指令
                    msg_handler(msg,c_fd);
                }
            }
            
        }
    }

    close(s_fd);
    close(c_fd);
    return 0;
}

客户端代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"

//分割字符串
char *getDesDir(char *msg)  
{
    char *p;
    p = strtok(msg, " ");
    p = strtok(NULL, " ");
    return p;
}


//把指令转化为整形数
int get_cmd_type(char *cmd)
{
    if(!strcmp("ls",cmd))         return LS;
    if(!strcmp("pwd",cmd))        return PWD;
    if(!strcmp("quit",cmd))       return QUIT;
    if(!strcmp("lls",cmd))        return LLS;

    if(strncmp("cd",cmd,2)==0)    return CD;
    if(strncmp("get",cmd,3)==0)   return GET;
    if(strncmp("put",cmd,3)==0)   return PUT;
    if(strncmp("lcd",cmd,3)==0)   return LCD;

    return -1;
}

//处理指令
int cmd_handler(struct Msg msg,int fd)
{
    // printf("msg.cmd = %s\n",msg.cmd);
    int ret = get_cmd_type(msg.cmd);
    char *dir = (char*)malloc(strlen(msg.cmd) + 1);
    int filefd;
    char buf[32]; //接收输入命令缓冲区

    switch (ret){
        case LS:
        case PWD:
        case CD:
        {
            write(fd,&msg,sizeof(msg));
            break;
        }

        /*从服务器上获取指定的文件*/
        case GET:
            write(fd,&msg,sizeof(msg));
            break;

        /*将本地客户端上的指定文件上传到服务器*/
        case PUT:  
            strcpy(buf,msg.cmd);
            dir = getDesDir(buf); //获取文件名
            if(access(dir,F_OK) == -1){
                printf("文件不存在\n");
            }else{
                filefd = open(dir,O_RDWR);
                read(filefd,msg.buf,sizeof(msg.buf));
                close(filefd);
                write(fd,&msg,sizeof(msg));
            }
            break;

        /*改变本地客户端的当前工作目录*/
        case LCD:
            dir = getDesDir(msg.cmd); //获取文件名
            if (chdir(dir) == -1) {
                printf("无法进入目录 %s\n", dir);
            }else{
                printf("进入目录成功\n");
            }
            break;

        /*列出本地客户端上的文件和目录*/
        case LLS:
            system("ls");
            break;

        case QUIT:
            strcpy(msg.cmd,"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;
    int filefd;
    char *filename =(char*)malloc(strlen(msg.cmd) + 1);
    struct Msg msgget;

    n_read = read(c_fd,&msgget,sizeof(msgget));
    //判断是否断开连接
    if(n_read == 0){
        printf("服务器已退出\n");
        exit(-1);
    }
    //判断是否执行get指令
    else if(msgget.type == DOFILE){
        filename = getDesDir(msg.cmd);
        printf("file=%s\n",filename);
        filefd = open(filename,O_RDWR|O_CREAT,0600);
        if (filefd < 0) {
            perror("open");
            exit(-1);
        }
        write(filefd,msgget.buf,sizeof(msgget.buf));
        close(filefd);
        putchar('>');
    }
    else{
        printf("------------------------------------\n");
        printf("%s\n",msgget.cmd);
        printf("------------------------------------\n");
        putchar('>');
        fflush(stdout);        
    }
}

int main(int argc,char** argv)
{
	int c_fd; 
    int n_read;
    int ret;
    struct Msg msg = {0};
    struct sockaddr_in c_addr;

    memset(&c_addr,0,sizeof(struct sockaddr_in));

	c_fd = socket(AF_INET,SOCK_STREAM,0);

	c_addr.sin_family = AF_INET; //选择协议族
	c_addr.sin_port = htons(atoi(argv[2])); //绑定端口号
	inet_aton(argv[1],&c_addr.sin_addr); //将IP地址转化成网络能识别的格式
    if(connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr)) == -1){
        perror("connect");
        exit(-1);
    } 
    printf("connect...\n");

    while(1){
        memset(msg.cmd,0,sizeof(msg.cmd));
        printf(">");
        fgets(msg.cmd, sizeof(msg.cmd), stdin);
        msg.cmd[strcspn(msg.cmd, "\n")] = 0; // 去掉换行符
        ret = cmd_handler(msg,c_fd); //处理指令并送给服务端

        if(ret > IFGO){
            putchar('>');
            fflush(stdout);
            continue;
        }
        if(ret == -1){
            printf("找不到该命令\n");
            putchar('>');
            fflush(stdout);
            continue;            
        }

        handler_server_message(c_fd,msg);
    }

	return 0;
}

 config.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 cmd[1024]; //指令接收缓冲区
        char buf[1024];  //数据传输缓冲区
};

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LJX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值