Linux C语言模拟FTP服务器

实现的功能如下:

服务端客户端
查看服务器路径下文件(ls)查看本地路径下文件(LS)
查看服务器路径(pwd)查看本地路径(PWD)
进入服务器某一路径(cd **)进入本地某一路径(CD **)
从服务器上获取某一文件(get **)
把本地某一文件上传到服务器上(put **)

功能大体上都能实现,代码的规范性,程序运行后文本的的格式还有待改善,可能还有一些尚未发现的bug,等日后有空再测试修改吧(明天开始上网课了-_-||)

myftp.h

#ifndef __MYFTP_H__                                                                                                                                                                                                 
#define __MYFTP_H__

#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define ERROR -1
#define LS 0
#define CD 1
#define PWD 2
#define GET 3
#define PUT 4
#define MYLS 5
#define MYPWD 6
#define MYCD 7

typedef struct Message{
    char cmd[128];
    char buf[1024];
    char content[2048];
}Msg;

//Public=================================================================
//Change cmd to number
int cmd_change(Msg msg){
    if(strstr(msg.cmd,"ls") != NULL)
        return LS;
    else if(strstr(msg.cmd,"pwd") != NULL)
        return PWD;
    else if(strstr(msg.cmd,"cd") != NULL)
        return CD;
    else if(strstr(msg.cmd,"get") != NULL)
        return GET;
    else if(strstr(msg.cmd,"put") != NULL)
        return PUT;
    else if(strstr(msg.cmd,"LS") != NULL)
        return MYLS;
    else if(strstr(msg.cmd,"PWD") != NULL)
        return MYPWD;
    else if(strstr(msg.cmd,"CD") != NULL)
        return MYCD;
    else if(strlen(msg.cmd) == 0){}
    else{
        printf("Commend:%s(%ld) is wrong!\n\n",msg.cmd,strlen(msg.cmd));
        printf("-----------------------------\n\n");
        return ERROR;
    }
}
//-----------------------------------------------------------------------
char* Get_file_name(Msg msg){
    char* file;
    file = strtok(msg.cmd," ");
    file = strtok(NULL," ");
    file[strlen(file) - 1] = '\0';
    return file;
}
//----------------------------------------------------------------------
void Server_write_to_client(Msg msg,int c_fd){
    char* file = Get_file_name(msg);
    memset(&msg,0,sizeof(msg));
    int fd = open(file,O_RDWR);
    int n_read = read(fd,msg.content,2048);
    if(n_read >= 0){
        strcpy(msg.buf,"Server write to client successfully!\n");
        int n_write = write(c_fd,&msg,sizeof(msg));
        if(n_write > 0){
            printf("Send success!\n");
        }
        else{
            perror("why");
        }
    }
    else{
        perror("Server_write_to_client");
        strcpy(msg.buf,"Server write to client failed!\n");
        write(c_fd,&msg,sizeof(msg));
    }
}
//----------------------------------------------------------------------
void Client_write_to_server(char* file,int c_fd){
    printf("client_file:%s\n",file);
    Msg msg;
    memset(&msg,0,sizeof(msg));
    int fd = open(file,O_RDWR);
    int n_read = read(fd,msg.content,2048);
    if(n_read > 0){
        printf("Client write to server successfully!\n");
        write(c_fd,&msg,sizeof(msg));
    }
    else{
        printf("Client write to server failed!\n");
    }
}
//------------------------------------------------------------------------
void Server_listen_from_client(char* file,int c_fd){
    Msg msg;                                                                                                                                                                                                        
    memset(&msg,0,sizeof(msg));
    int n_read = read(c_fd,&msg,sizeof(msg));
    if(n_read > 0){
        int fd = open(file,O_RDWR|O_CREAT,0600);
        if(fd > 0){
            int n_write = write(fd,msg.content,strlen(msg.content));
            if(n_write > 0){
                strcpy(msg.buf,"Server listen from client successfully!\n");
                write(c_fd,&msg,sizeof(msg));
            }
            else{
                strcpy(msg.buf,"Server listen from client failed!\n");
                write(c_fd,&msg,sizeof(msg));
            }
        }
        else{
            printf("file = %s\n",file);
            perror("Server create file failed!\n\n");
        }
    }
    else{
        printf("Server read pipe failed\n\n");
    }
}
//-----------------------------------------------------------------------
void Client_listen_from_server(char* filename,int c_fd){
    Msg msg;
    memset(&msg,0,sizeof(msg));
    int n_read = read(c_fd,&msg,sizeof(msg));
    if(n_read > 0){
        printf("Recv success!\n");
        printf("content:\n%s\n",msg.content);
        printf("%ld:%s\n",strlen(filename),filename);
        int fd = open(filename,O_RDWR|O_CREAT,0600);
        if(fd > 0){
            int n_write = write(fd,msg.content,strlen(msg.content));
            if(n_write > 0){ 
                printf("Client listen from server successfully!\n");
            }   
            else{
                printf("Client listen from server failed!\n");
            }
        }
        else{
            printf("Client listen from server failed!\n");
        }   
    }
    else{
        perror("Recv failed");
    }
}

//Server=================================================================
//Server:handle cmd
void server_cmd_handle(int c_fd,Msg msg,int num){
    if(num == LS){
        Msg msg;
        FILE* fp = popen("ls","r");
        memset(&msg,0,sizeof(msg));
        int n_read = fread(msg.buf,1,2048,fp);
        if(n_read <= 0){  
            perror("Server_read");
        }
        else{ 
            write(c_fd,&msg,sizeof(msg));
        }                     
    }

    else if(num == PWD){ 
        Msg msg;
        FILE* fp = popen("pwd","r");
        memset(&msg,0,sizeof(msg));
        int n_read = fread(msg.buf,1,2048,fp);
        if(n_read <= 0){  
            perror("Server_read");
        }
        else{ 
            write(c_fd,&msg,sizeof(msg));
        }       
    }
else if(num == CD){      
        //1.get file name   
        char* file = Get_file_name(msg);

        //2.get all file's name which is in the server
        FILE* fp = popen("ls","r");
        char* Rbuf = (char*)malloc(2048 * sizeof(char));
        memset(Rbuf,0,2048);
        fread(Rbuf,1,2048,fp);
        fclose(fp);

        //3.check if it exiits 
        if(strstr(file,"..") != NULL || strstr(Rbuf,file) != NULL){
            int ret = chdir(file);
            if(ret == 0){ 
                char* buf = "Success!\n";
                write(c_fd,buf,strlen(buf));
            }
            else{
                perror("Server_CD_chdir");
                exit(-1);
             }   
        }
        else{
            char* buf = "File is not exist!";
            write(c_fd,buf,strlen(buf));
            exit(-1);
        }
    }

    else if(num == GET){
        int n_read,n_write,fd;
        //1.get file name   
        char* file = Get_file_name(msg);
        printf("server want to get %s\n\n",file);
        //2.get all file's name which is in the server
        FILE* fp = popen("ls","r");
        char* Rbuf = (char*)malloc(2048 * sizeof(char));
        fread(Rbuf,1,2048,fp);
        fclose(fp);
        //3.copy and send txt
        if(strstr(Rbuf,file) != NULL){
            Server_write_to_client(msg,c_fd);                                                                                                                                                                       
        }
    }
else if(num == PUT){
        char* file = Get_file_name(msg);
        printf("Client put %s\n\n",file);
        char* filename;
        filename = (char*)malloc(20 * sizeof(char));
        strcpy(filename,file);
        printf("Client put %s\n\n",filename);
        Server_listen_from_client(filename,c_fd);   
    }    
}
//client======================================================
//Client:handle cmd
void client_cmd_handle(int c_fd,Msg msg,int num){

    if(num == MYLS){
        FILE* fp = popen("ls","r");
        char* Rbuf = (char*)malloc(2048 * sizeof(char));
        memset(Rbuf,0,2048);
        int Rtypes = fread(Rbuf,1,2048,fp);
        printf("\n%s\n------------------------------\n\n",Rbuf);
        pclose(fp);
    }
 
    else if(num == MYPWD){
        FILE* fp = popen("pwd","r");
        char* Rbuf = (char*)malloc(2048 * sizeof(char));
        memset(Rbuf,0,2048);
        int Rtypes = fread(Rbuf,1,2048,fp);
        printf("\n%s\n------------------------------\n\n",Rbuf);
        pclose(fp);
    } 
else if(num == MYCD){ 
        //1.get file name   
        char* file = Get_file_name(msg);
        //2.get all file's name which is in the client
        FILE* fp = popen("ls","r");
        char* Rbuf = (char *)malloc(2048 * sizeof(char));
        memset(Rbuf,0,2048);
        fread(Rbuf,1,2048,fp);
        fclose(fp);
        //3.check if it exiits 
        if(strstr(file,"..") != NULL || strstr(Rbuf,file) != NULL){
            int ret = chdir(file);
            if(ret == 0){
                printf("\nSuccess!\n\n------------------------------\n\n");
            }else{
                perror("Server_cd");
                exit(-1);
             }    
        }else{
            printf("\nFile is not exist!\n\n------------------------------\n\n");
            exit(-1);
         }
    }
}

#endif   

server.c

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

int main(int argc,char** argv){
    int s_fd,c_fd,ret,c_len,fd,key;
    Msg msg;
    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));

    if(argc != 2){
        printf("Param wrong!\n");
        exit(-1);
    }
    //=============================================================================  connext
    //socket
    s_fd = socket(AF_INET,SOCK_STREAM,0);
    if(s_fd  == -1){ 
        perror("Server_socket");
        exit(-2);
    }                                                                                                                                   
    //bind
    s_addr.sin_family = AF_INET;
    s_addr.sin_port = htons(atoi(argv[1]));
    inet_aton("192.168.95.130",&s_addr.sin_addr);
    ret = bind(s_fd,(struct sockaddr *)&s_addr,sizeof(struct sockaddr_in));
    if(ret ==  -1){
        perror("Server_bind");
        exit(-3);
    }
    //listen
    listen(s_fd,10);
    //accept
    c_len = sizeof(struct sockaddr_in);
    c_fd = accept(s_fd,(struct sockaddr*)&c_addr,&c_len);
    if(c_fd == -1){
        perror("Server_accept");
		exit(-4);
    }else{
        printf("-------------------------------------\n\n");
        printf("%s connected\n\n",inet_ntoa(c_addr.sin_addr));
        printf("-------------------------------------\n\n");
    }
    //=============================================================================  work
    //while{
    while(1){
        memset(&msg,0,sizeof(msg));
        int n_read = read(c_fd,&msg,sizeof(msg));
        printf("read:%s\n",msg.cmd);
        //handle key
        key = cmd_change(msg);
        server_cmd_handle(c_fd,msg,key);
    }
    return 0;
}                                                       

client.c

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

int main(int arc,char** argv){
    int c_fd,fd,key;
    Msg msg;
    char* file = NULL;
    struct sockaddr_in c_addr;
    memset(&c_addr,0,sizeof(struct sockaddr_in));
    if(arc != 3){
        printf("Param wrong!\n");
        exit(-1);
    } 
    //=================================================================================================connect
    //socket
    c_fd = socket(AF_INET,SOCK_STREAM,0);
    if (c_fd  == -1){ 
        perror("Client_socket");
        exit(-2);
    } 
    //connect
    c_addr.sin_family = AF_INET;
    c_addr.sin_port = htons(atoi(argv[2]));

    inet_aton(argv[1],&c_addr.sin_addr);
    int ret = connect(c_fd,(struct sockaddr *)&c_addr,sizeof(struct sockaddr_in));
    if(ret ==  -1){
        perror("Client_connect");
        exit(-3);
    }else{
        printf("-------------------------------------\n\n");
        printf("Connected successfully!\n\n");
        printf("-------------------------------------\n\n");
    }  
    //==================================================================================================work
    //while(){
    while(1){
        fd = fork();
        // send msg
        if(fd == 0){
            while(1){
                printf(">");
                memset(&msg,0,sizeof(msg));
                fgets(msg.cmd,128,stdin);
                key = cmd_change(msg);
                if(key == CD || key == GET || key == PUT || key == MYCD){
                    char* filename = Get_file_name(msg);
                    file = (char*)malloc(20*sizeof(char));
                    strcpy(file,filename);
                }
                if(key < 5 && key >= 0){
                    int n_write = write(c_fd,&msg,sizeof(msg));
                    if(key == PUT){
                        Client_write_to_server(file,c_fd);
                    }
                    else if(key == GET){
                        Client_listen_from_server(file,c_fd);       
                    }
                }
                
                else if(key >= 5){ 
                    client_cmd_handle(c_fd,msg,key);
                }
                else
                    continue;
            }
        }
        while(1){  
            //recv msg
            memset(msg.buf,0,strlen(msg.buf));
            int n_read = read(c_fd,&msg,sizeof(msg));
            printf("\n%s\n",msg.buf);
            printf("-------------------------------------\n\n");
        }  
    } 
    return 0;
} 
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值