基于socket的文件传输协议

1、我们先搭建一个一个服务器与客户机并使他们进行通信
2、在客户机中对输入的指令进行判断,将指令转化成对应的枚举类型发送给服务机
3、服务机对发送过来的FTP_CMD的值进行判断,并执行相对应的功能
4、ls功能的实现:通过popen实现,获取内容发送客户机并显示
get 对指令进行分割,读取分割后的文件名所对应的文件,之后将读取后的数据发送给服务机
put 对指令进行分割,将文件读取到data中,发送给客户机,并在服务器中创建文件,将内容写入
quit 直接退出
cd 采用chdir来实现
用户名和密码的实现:从文件读取密码以及账号与用户输入的进行对比,一致通过反之停止
服务器代码

#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include <errno.h>
#include "msg.h"
#include "log.h"
#include "utils.h"

int g_running;

/**
 *
 * @param in_cmd
 * @param out_cmd
 */
void handle_cmd(struct Msg *in_cmd, struct Msg *out_cmd)
{
    FILE *fp = NULL;
    int ret;

    out_cmd->cmd = in_cmd->cmd;

    switch(in_cmd->cmd) {
        case FTP_CMD_LS:
            fp = popen(in_cmd->args, "r");
            if (NULL != fp) {
                ret = fread(out_cmd->data, 1, sizeof(out_cmd->data), fp);
                //ret = fread(out_cmd->data, sizeof(out_cmd->data), 1, fp);
                log_write("fread ret %d, eof %d, data %s\n",
                        ret, feof(fp), out_cmd->data);
                pclose(fp);
            }
            break;
        default:
            break;
    }
}

/**
 * @brief 澶勭悊瀹㈡埛绔殑鍛戒护in_cmd锛屾妸缁撴灉鍐欏叆out_cmd
 *
 * @param in_cmd
 * @param out_cmd
 */
void handle_cmd2(struct Msg *in_cmd, struct Msg *out_cmd)
{
    static struct LinkList *hist = NULL;

    log_write("cmd %d, args %s\n", in_cmd->cmd, in_cmd->args);

    out_cmd->cmd = in_cmd->cmd;

    linklist_insert(&hist, in_cmd->args);

    if (FTP_CMD_LS == in_cmd->cmd) {
        FILE *fp = popen(in_cmd->args, "r");
        if (fp != NULL) {
            int ret = fread(out_cmd->data, 1, sizeof(out_cmd->data), fp);
            log_write("fread ret %d, %s", ret, out_cmd->data);
            pclose(fp);
        }
    } else if (FTP_CMD_HIST == in_cmd->cmd) {
        linklist_get_cmd(hist, out_cmd->data);
    } else if (FTP_CMD_CD == in_cmd->cmd) {
        char dirname[32];

        if (split_string2(in_cmd->args, dirname) < 0) {
            return;
        }

        int ret = chdir(dirname);
        log_write("chdir ret %d", ret);
    } else if (FTP_CMD_QUIT == in_cmd->cmd) {
        log_write("quit\n");
        g_running = 0;
    } else if (FTP_CMD_GET == in_cmd->cmd) {
        char filename[32];
        if (split_string2(in_cmd->args, filename) < 0) {
            out_cmd->cmd = FTP_CMD_ERROR;
            log_write("filename not find\n");
            return;
        }

        long length = get_length(filename);
        if (length < 0 || length > sizeof(out_cmd->data)) {
            out_cmd->cmd = FTP_CMD_ERROR;
            log_write("get_length failed, filename %s\n", filename);
            return;
        }

        get_md5(filename, out_cmd->md5);

        FILE *fp = fopen(filename, "r");
        if (fp != NULL) {
            int ret = fread(out_cmd->data, 1, length, fp);
            out_cmd->data_length = ret;
            log_write("fread ret %d, eof %d\n", ret, feof(fp));
            fclose(fp);
        } else {
            out_cmd->cmd = FTP_CMD_ERROR;
            log_write("filename not find %s\n", filename);
        }
    } else if (FTP_CMD_PUT == in_cmd->cmd) {
        // 鑾峰彇鏂囦欢鍚?浠?寮€澶?
        char filename[32];
        filename[0] = '+';
        split_string2(in_cmd->args, &filename[1]);

        FILE *fp = fopen(filename, "w");
        if (fp != NULL) {
            int ret = fwrite(in_cmd->data, 1, in_cmd->data_length, fp);
            log_write("fwrite ret %d, filename %s, data_length %d\n",
                      ret, filename, in_cmd->data_length);
            fclose(fp);
        }

        // 瀵规瘮瀹㈡埛绔殑md5
        char md5[64];
        get_md5(filename, md5);
        if (memcmp(md5, in_cmd->md5, 32) != 0) {
            remove(filename);
            log_write("client %s, server %s\n", in_cmd->md5, md5);
        }
    }
}

int main(int argc, char **argv)
{
    struct sockaddr_in serveraddr;
    int listenfd;
    int sock;
    int ret;
    struct Msg *msg_recv = NULL;
    struct Msg *msg_send = NULL;

    msg_recv = (struct Msg *)malloc(sizeof(struct Msg));
    msg_send = (struct Msg *)malloc(sizeof(struct Msg));

    log_create("server.txt");

    // socket
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd < 0) {
        log_write("socket failed, ret %d\n", listenfd);
        return -1;
    }

    // bind绔彛锛孲ERVER_PORT
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = SERVER_PORT;
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    int on = 1;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));

    ret = bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    if (ret < 0) {
        log_write("bind failed, ret %d, errno %d %s\n", ret, errno, strerror(errno));
        return -1;
    }
    ret = listen(listenfd, 0);
    if (ret < 0) {
        log_write("listen failed ,ret  %d\n", ret);
        return -1;
    }
    sock = accept(listenfd, NULL, 0);
    if (ret < 0) {
        log_write("accept failed ,ret  %d\n", ret);
        return -1;
    }

    log_write("client connect.\n");

    struct Auth auth;
    ret = recv(sock, &auth, sizeof(struct Auth), 0);
    log_write("%s %s\n", auth.username, auth.password);

    struct Auth server;
    FILE *fp = fopen("passwd", "r");
    if (fp != NULL) {
        fscanf(fp, "%s %s", server.username, server.password);
        log_write("server %s %s\n", server.username, server.password);
        fclose(fp);
    }

    if (0 != memcmp(auth.username, server.username, strlen(server.username)) ||
        0 != memcmp(auth.password, server.password, strlen(server.password))) {
        // 涓嶄竴鏍?
        auth.cmd = FTP_CMD_ERROR;
        log_write("auth failed\n");
    }


    ret = send(sock, &auth, sizeof(struct Auth), 0);
    log_write("send %d\n", ret);

    if (FTP_CMD_ERROR == auth.cmd) {
        return -1;
    }

    g_running = 1;

    while (g_running) {
        ret = recv(sock, msg_recv, sizeof(struct Msg), 0);
        log_write("recv %d\n", ret);

        memset(msg_send, 0, sizeof(struct Msg));
        handle_cmd2(msg_recv, msg_send);

        ret = send(sock, msg_send, sizeof(struct Msg), 0);
        log_write("send %d\n", ret);
    }

    log_destroy();
    return 0;
}

客户机

#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include "log.h"
#include "msg.h"
#include "utils.h"



enum FTP_CMD get_cmd(char *buf, struct Msg *msg)
{
    char *ptr_args;

    if (0 == memcmp(buf, "ls", 2)) {
        return FTP_CMD_LS;
    }

    return FTP_CMD_ERROR;
}


int handle_user_input(struct Msg *msg_send)
{
    char buf[32];
    enum FTP_CMD cmd;

    printf("input cmd:\n");
    fgets(buf, 32, stdin);
    log_write("%s\n", buf);


    cmd = get_cmd(buf, msg_send);
    log_write("cmd %d\n", cmd);
    if (cmd == FTP_CMD_ERROR) {
        return -1;
    }


    msg_send->cmd = cmd;
    strcpy(msg_send->args, buf);

    return 0;
}

int handle_user_input2(struct Msg *msg_send)
{
    char buf[32];
    enum FTP_CMD cmd;


    fgets(buf, 32, stdin);


    log_write("%s", buf);



    if (0 == memcmp(buf, "ls", 2)) {
        cmd = FTP_CMD_LS;
    } else if (0 == memcmp(buf, "hist", 4)) {
        cmd = FTP_CMD_HIST;
    } else if (0 == memcmp(buf, "cd", 2)) {
        cmd = FTP_CMD_CD;
    } else if (0 == memcmp(buf, "get", 3)) {
        cmd = FTP_CMD_GET;
    } else if (0 == memcmp(buf, "quit", 4)) {
        cmd = FTP_CMD_QUIT;
    } else if (0 == memcmp(buf, "put", 3)) {
        cmd = FTP_CMD_PUT;

        char filename[32];
        if (split_string2(buf, filename) < 0) {
            log_write("filename not find");
            return -1;
        }

        long length = get_length(filename);

        if (length < 0 || length > sizeof(msg_send->data)) {
            log_write("get_length failed, length %d\n", length);
            return -1;
        }


        get_md5(filename, msg_send->md5);


        // #define NULL 0
        FILE *fp = fopen(filename, "r");
        if (NULL != fp) {
            // 璁剧疆data_length
            msg_send->data_length = fread(msg_send->data, 1, length, fp);
            log_write("fread %d", msg_send->data_length);
            fclose(fp);
        } else {
            log_write("filename not find, %s", filename);
            return -1;
        }
    } else {
        cmd = FTP_CMD_ERROR;
    }


    if (cmd == FTP_CMD_ERROR) {
        return -1;
    }


    msg_send->cmd = cmd;
    strcpy(msg_send->args, buf);


    return 0;
}

int main(int argc, char **argv)
{
    int ret;
    int sock;
    struct sockaddr_in serveraddr;
    struct Msg *msg_send = NULL;
    struct Msg *msg_recv = NULL;
    msg_send = (struct Msg *)malloc(sizeof(struct Msg));
    msg_recv = (struct Msg *)malloc(sizeof(struct Msg));

    log_create("client.txt");


    sock = socket(AF_INET, SOCK_STREAM, 0);

  
    memset(&serveraddr, 0, sizeof(serveraddr));
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = SERVER_PORT;
    serveraddr.sin_addr.s_addr = inet_addr("127.0.0.1");


    // 3. 杩炴帴connect
    ret = connect(sock, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
    if (ret < 0) {
     
        log_write("connect failed, ret %d\n", ret);
        return -1;
    }


    log_write("connect server sucess\n");

    struct Auth auth;


    printf("username:");
    scanf("%s", auth.username);
    printf("password:");
    scanf("%s", auth.password);
    auth.cmd = FTP_CMD_AUTH;


    ret = send(sock, &auth, sizeof(struct Auth), 0);
    log_write("send ret %d", ret);


    ret = recv(sock, &auth, sizeof(struct Auth), 0);
    if (FTP_CMD_ERROR == auth.cmd) {
        printf("username or password error\n");
        return -1;
    }
    printf("well done\n");

    while(1) {

     
        if (handle_user_input2(msg_send) < 0) {
            continue;
        }


        ret = send(sock, msg_send, sizeof(struct Msg), 0);
        log_write("send ret %d\n", ret);


        ret = recv(sock, msg_recv, sizeof(struct Msg), 0);
        log_write("recv ret %d\n", ret);
        log_write("cmd %d\n", msg_recv->cmd);
        log_write("data %s\n", msg_recv->data);


        if (FTP_CMD_HIST == msg_recv->cmd || FTP_CMD_LS == msg_recv->cmd) {
            printf("%s", msg_recv->data);
        } else if (FTP_CMD_GET == msg_recv->cmd) {
            // get file.txt
            // file.txt
            // _file.txt
            char filename[32];
            filename[0] = '_';
            split_string2(msg_send->args, &filename[1]);
            FILE *fp = fopen(filename, "w");
            if (fp != NULL) {
                ret = fwrite(msg_recv->data, 1, msg_recv->data_length, fp);
                log_write("fwrite ret %d", ret);
                fclose(fp);
            }

            char md5[64];
            get_md5(filename, md5);
            if (memcmp(md5, msg_recv->md5, 32) != 0) {
                remove(filename);
                log_write("client %s, server %s\n", msg_recv->md5, md5);
            }
        } else if (FTP_CMD_QUIT == msg_recv->cmd) {
            printf("byebye\n");
            break;
        }

    }

    log_destroy();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值