美文网首页
网络通信三——1-13

网络通信三——1-13

作者: 赋闲 | 来源:发表于2017-02-20 11:20 被阅读0次
    // my_ftp_server.h
    // 声明文件服务器的相关函数和常量
    
    // 配置文件服务器的根目录
    #define SERVER_ROOT_DIR "/home/vicliu/my_ftp_root"
    
    // 响应客户端的list命令
    // conn_fd  通过指定的连接套接字传递数据
    void put_list_data_to_client(int conn_fd);
    
    // 响应客户端的get命令
    // conn_fd  连接套接字
    // file     客户端待下载的文件名
    void put_file_data_to_client(int conn_fd, char *file);
    
    // 响应客户端的put命令
    // conn_fd  连接套接字
    // file     客户端待上传的文件名
    void get_file_data_from_client(int conn_fd, char *file);
    
    // my_ftp_client.h
    // 文件服务器客户端的函数声明
    
    // 客户端的list执行函数
    void get_list_data_from_server(int sock_fd);
    
    // 客户端的get执行函数
    void get_file_data_from_server(int sock_fd, char *file);
    
    // 客户端的put执行函数
    void put_file_data_to_server(int sock_fd, char *file);
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include "my_header.h"
    #include "my_ftp_client.h"
    
    #define N 150
    
    int main(int argc, char *argv[])
    {
        if(argc != 3)
        {
            printf("usage : %s <server_ip> <server_port>\n", argv[0]);
            return 1;
        }
        
        int sock_fd = 0;
        struct sockaddr_in serveraddr;
        char buf[N] = {'\0'};
        
        struct data_package pkg;
        memset(&pkg, 0, sizeof(pkg));
    
        // 1.socket
        sock_fd = socket(AF_INET, SOCK_STREAM, 0);
        
        // 2.connect
        memset(&serveraddr, 0, sizeof(serveraddr));
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
        serveraddr.sin_port = htons(atoi(argv[2]));
        connect(sock_fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
        
        // 3.循环从键盘读入命令并构造数据结构体发送给服务器
        while(1)
        {
            // 3.1输入
            printf("my_ftp>");
            fgets(buf, N, stdin);
            buf[strlen(buf)-1] = '\0';  // 消除'\n'
            
            // 3.2构造结构体发送,并准备接收服务器发来的数据
            if(strncmp(buf, "list", 4) == 0)
            {
                pkg.cmd = CMD_LIST;
                send(sock_fd, &pkg, sizeof(pkg), 0);
                // 执行接收list数据
                get_list_data_from_server(sock_fd);
            }
            else if(strncmp(buf, "get ", 4) == 0)
            {
                pkg.cmd = CMD_GET;
                strcpy(pkg.filename, buf+4);
                send(sock_fd, &pkg, sizeof(pkg), 0);
                // 执行下载函数
                get_file_data_from_server(sock_fd, buf+4);
            }
            else if(strncmp(buf, "put ", 4) == 0)
            {
                pkg.cmd = CMD_PUT;
                strcpy(pkg.filename, buf+4);
                send(sock_fd, &pkg, sizeof(pkg), 0);
                // 执行上传函数
                put_file_data_to_server(sock_fd, buf+4);
            }
            else if(strncmp(buf, "quit", 4) == 0)
            {
                pkg.cmd = CMD_QUIT;
                send(sock_fd, &pkg, sizeof(pkg), 0);
                // 执行退出操作
                printf("client quit...\n");
            }
            else 
            {
            }
        }
        
        // 4.close
        close(sock_fd);   
        
        return 0;
    }
    
    // 客户端的list执行函数
    void get_list_data_from_server(int sock_fd)
    {
        struct data_package pkg;
           
        // 循环接收并打印,直到收到结束标志为止
        while(1)
        {
            memset(&pkg, 0, sizeof(pkg));
            
            recv(sock_fd, &pkg, sizeof(pkg), 0);
            
            if(pkg.cmd != CMD_LIST)
                continue;
                
            if(pkg.flag == DATA_END_FLAG)
                break;
                
            // 打印数据
            printf("%s\n", pkg.data);
        }
    }
    
    // 客户端的get执行函数
    void get_file_data_from_server(int sock_fd, char *file)
    {
        struct data_package pkg;
        int fd = 0;
        int n = 0;
    
        // 1.打开待下载文件,如果文件不存在则创建,如果文件存在,则将其数据截短为0
        fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        
        // 2.循环读取服务器发送来的数据,并写入文件
        while(1)
        {
            recv(sock_fd, &pkg, sizeof(pkg), 0);
            
            if(pkg.cmd != CMD_GET)
                continue;
            
            if(pkg.flag == DATA_END_FLAG)
                break;
            
            n = strlen(pkg.data);   // 实际数据长度
            write(fd, pkg.data, n);
        }
        
        // 3.关闭文件
        close(fd);
    }
    
    // 客户端的put执行函数
    void put_file_data_to_server(int sock_fd, char *file)
    {
        struct data_package pkg;
        int fd;
    
        // 1.判断待上传文件是否存在,如果不存在,则发送数据结束状态包
        if(access(file, F_OK) == -1)
        {
            memset(&pkg, 0, sizeof(pkg));
            pkg.cmd = CMD_PUT;
            pkg.flag = DATA_END_FLAG;
            
            send(sock_fd, &pkg, sizeof(pkg), 0);
            
            return;
        }
        
        // 2.打开文件
        fd = open(file, O_RDONLY);
        
        // 3.循环读取文件内容,发送给服务器
        memset(&pkg, 0, sizeof(pkg));
        pkg.cmd = CMD_PUT;
        pkg.flag = 0;
        while(read(fd, pkg.data, MAX_DATA_LEN-1) > 0)
        {
            send(sock_fd, &pkg, sizeof(pkg), 0);
            
            memset(pkg.data, 0, MAX_DATA_LEN);
        }   
        
        // 4.构建数据结束状态包发送给服务器
        memset(&pkg, 0, sizeof(pkg));
        pkg.cmd = CMD_PUT;
        pkg.flag = DATA_END_FLAG;
        send(sock_fd, &pkg, sizeof(pkg), 0);
        
        // 5.关闭文件
        close(fd);
    }
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <dirent.h>
    #include "my_header.h"
    #include "my_ftp_server.h"
    
    int main(int argc, char *argv[])
    {
        if(argc != 3)
        {
            printf("usage : %s <server_ip> <server_port>\n", argv[0]);
            return 1;
        }
        
        int sock_fd = 0;
        int conn_fd = 0;
        int n = 0;
        struct sockaddr_in serveraddr;
        struct sockaddr_in clientaddr;
        socklen_t len = 0;
        
        // 存储客户端和服务器的交互数据
        struct data_package pkg;
        
        memset(&pkg, 0, sizeof(pkg));
    
        // 1.socket
        sock_fd = socket(AF_INET, SOCK_STREAM, 0);
        
        // 2.bind
        serveraddr.sin_family = AF_INET;
        serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
        serveraddr.sin_port = htons(atoi(argv[2]));
        bind(sock_fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
        
        // 3.listen
        listen(sock_fd, 15);
        
        // 4.accept
        while(1)
        {
            printf("waiting for connetion...\n");
            len = sizeof(clientaddr);
            conn_fd = accept(sock_fd, (struct sockaddr *)&clientaddr, &len);
            
            printf("connection with %s : %d\n", 
                inet_ntoa(clientaddr.sin_addr),
                ntohs(clientaddr.sin_port));
            
            while(1)
            {
                // 循环读取客户端发送来的数据,分析并执行相应操作
                // 直到客户端退出为止
                n = recv(conn_fd, &pkg, sizeof(pkg), 0);
                switch(pkg.cmd)
                {
                    case CMD_LIST:
                        // 执行list操作
                        put_list_data_to_client(conn_fd);
                        break;
                    case CMD_GET:
                        // 执行get操作
                        put_file_data_to_client(conn_fd, pkg.filename);
                        break;
                    case CMD_PUT:
                        // 执行put操作
                        get_file_data_from_client(conn_fd,  pkg.filename);
                        break;
                    case CMD_QUIT:
                        printf("server quit...\n");
                        // 执行quit操作
                        break;
                    default:
                        break;
                }
            }
            
            // 5.关闭连接套接字
            close(conn_fd);
        }
        
        // 6.close监听套接字
        close(sock_fd);
        
        return 0;
    }
    
    
    // 响应客户端的list命令
    // conn_fd  通过指定的连接套接字传递数据
    void put_list_data_to_client(int conn_fd)
    {
        struct data_package pkg;
    
        // 1.打开文件服务器根目录
        DIR *p_dir = opendir(SERVER_ROOT_DIR);
        
        // 2.循环读取目录项信息,发送给客户端
        struct dirent *p = NULL;
        while((p = readdir(p_dir)) != NULL)
        {
            if(strncmp(p->d_name, ".", 1) == 0)
                continue;
        
            memset(&pkg, 0, sizeof(pkg));
            pkg.cmd = CMD_LIST;
            strcpy(pkg.data, p->d_name);
            pkg.flag = 0;
            
            send(conn_fd, &pkg, sizeof(pkg), 0);
        }
        
        // 2.1发送数据结束状态数据包
        memset(&pkg, 0, sizeof(pkg));
        pkg.cmd = CMD_LIST;
        pkg.flag = DATA_END_FLAG;       // 结束标志
        send(conn_fd, &pkg, sizeof(pkg), 0);
        
        // 3.关闭目录
        closedir(p_dir);
    }
    
    // 响应客户端的get命令
    // conn_fd  连接套接字
    // file     客户端待下载的文件名
    void put_file_data_to_client(int conn_fd, char *file)
    {
        struct data_package pkg;
        char path[MAX_FILE_NAME_LEN] = {'\0'};
        int fd = 0;
        
        // 构造待下载文件在服务器文件系统中的绝对路径
        sprintf(path, "%s/%s", SERVER_ROOT_DIR, file);
    
        // 1.判断待下载文件是否存在,如果不存在,直接发送数据结束状态包 
        if(access(path, F_OK) == -1)
        {
            memset(&pkg, 0, sizeof(pkg));
            pkg.cmd = CMD_GET;
            pkg.flag = DATA_END_FLAG;
            
            send(conn_fd, &pkg, sizeof(pkg), 0);
            
            return;
        }
        
        // 2.如果文件存在,打开文件
        fd = open(path, O_RDONLY);
        
        // 3.循环的读取文件内容,发送给客户端
        memset(&pkg, 0, sizeof(pkg));
        pkg.cmd = CMD_GET;
        pkg.flag = 0;
        while(read(fd, pkg.data, MAX_DATA_LEN-1) > 0)
        {
            send(conn_fd, &pkg, sizeof(pkg), 0);
            memset(pkg.data, 0, MAX_DATA_LEN);
        }
            
        // 4.构造数据结束状态包
        memset(&pkg, 0, sizeof(pkg));
        pkg.cmd = CMD_GET;
        pkg.flag = DATA_END_FLAG;
        send(conn_fd, &pkg, sizeof(pkg), 0);
        
        // 5.关闭文件
        close(fd);
    }
    
    // 响应客户端的put命令
    // conn_fd  连接套接字
    // file     客户端待上传的文件名
    void get_file_data_from_client(int conn_fd, char *file)
    {
        struct data_package pkg;
        int fd = 0;
        int n = 0;
        char path[MAX_FILE_NAME_LEN] = {'\0'};
    
        // 构建待上传文件在服务器文件系统中的绝对路径
        sprintf(path, "%s/%s", SERVER_ROOT_DIR, file);
    
        // 1.打开文件,如果文件不存在,则创建;如果文件存在,则将其长度截短为0
        fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        
        // 2.循环读取文件内容,写入文件
        while(1)
        {
            recv(conn_fd, &pkg, sizeof(pkg), 0);
            
            if(pkg.cmd != CMD_PUT)
                continue;
                
            if(pkg.flag == DATA_END_FLAG)
                break;
            
            n = strlen(pkg.data);
            write(fd, pkg.data, n);
        }
        
        // 3.关闭文件
        close(fd);
    }
    

    相关文章

      网友评论

          本文标题:网络通信三——1-13

          本文链接:https://www.haomeiwen.com/subject/gwkfwttx.html