简易网络文件拷贝的C实现

效果

服务端

./s

客户端读服务端文件

./c 127.0.0.1 src_file dst_file 0 

客户端写文件到服务端

 ./c 127.0.0.1 src_file dst_file 1

服务端实现server.c

#include <stdio.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include "cs.c"

int init_socket(void)
{
        int opt = 1;
        struct sockaddr_in servaddr = {0};
        unsigned int len = sizeof(opt);
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        bool ok = false;

        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        servaddr.sin_port = htons(SERVICE_PORT);

        if(sock < 0) {
                perror("socket");
        } else if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, len)) {
                perror("setsockopt");
        } else if (bind(sock, (struct sockaddr *)&servaddr,sizeof(servaddr))) {
                perror("bind");
        } else if (listen(sock, 1)) {
                perror("listen");
        } else {
                ok = true;
        }
        if(ok) {
                /* null */
        } else if(sock >= 0) {
                close(sock);
        }
        return ok ? sock : -1;
}

void *server_thread(void *args)
{
        struct trans_op *op = (struct trans_op *)malloc(sizeof(*op));
        int client = *(int *)args;

        if(op) {
                perror("malloc");
        } else {
                op->magic = 0;
        }
        if(!op) {
                /* null */
        } else if(client < 0) {
                /* null */
        } else if (safe_recv(client, op,sizeof(*op), 0) == sizeof(*op)) {
                /* null */
        } else {
                printf("recv op err\n");
        }
        if(op->magic != START_EXIT) {
                printf("op->magic != START_EXIT\n");
        } else {
                switch(op->read_write) {
                        case READ_OP:
                                printf("client read file:%s -> %s\n", op->src_file, op->dst_file);
                                client_read_file(client, op);
                                break;
                        case WRITE_OP:
                                printf("client write file:%s -> %s\n", op->src_file, op->dst_file);
                                client_write_file(client, op);
                                break;
                        default:
                                break;
                }
        }
        if(!op) {
                /* null */
        } else {
                free(op);
        }
        if(client < 0) {
                /* null */
        } else {
                close(client);
        }
        return NULL;
}
int main(int argc, char *argv[])
{
        int client = -1;
        int  socklen = sizeof(struct sockaddr_in);
        struct sockaddr_in clientaddr = {0};
        int sock = init_socket();

        while(sock >= 0) {
                client = accept(sock,(struct sockaddr *)&clientaddr,(socklen_t*)&socklen);
                if(client < 0) {
                        perror("accept");
                } else {
                        printf("detect client:%d\n", client);
                        pthread_t tid = 0;
                        pthread_create(&tid, NULL, server_thread, &client);
                        if(tid) {
                                /* null */
                        } else {
                                pthread_detach(tid);
                        }
                }
        }
        return 0;
}

void client_read_file(int client, struct trans_op *op)
{
        // server read to -> client
        __read(client, op, op->src_file);
}
void client_write_file(int client, struct trans_op *op)
{
        // client send to -> server
        __write(client, op, op->dst_file);
}

客户端实现client.c

#include <stdio.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdint.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "cs.c"

int init_socket(int argc, char *argv[])
{
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        int opt = 1; unsigned int len = sizeof(opt);
        struct sockaddr_in servaddr = {0};
        bool ok = false;

        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr(argv[1]);
        servaddr.sin_port = htons(SERVICE_PORT);

        if(sock < 0) {
                perror("socket");
        } else if(setsockopt(sock , SOL_SOCKET, SO_REUSEADDR, &opt, len)) {
                perror("setsockopt");
        } else if(connect(sock, (struct sockaddr *)&servaddr, sizeof(servaddr))) {
                perror("connect");
        } else {
                ok = true;
        }
        if(ok) {
                /* null */
        } else if(sock >= 0){
                close(sock);
        }
        return ok ? sock : -1;
}

int main(int argc, char *argv[])
{
        int sock = -1;
        struct trans_op *op = (struct trans_op *)malloc(sizeof(*op));

        if(argc != 5) {
                printf("for read ./c 127.0.0.1 srcFile dstFile 0\n");
                printf("for write ./c 127.0.0.1 srcFile dstFile 1\n");
        } else if(!op) {
                perror("malloc");
        } else if((sock = init_socket(argc, argv)) == -1) {
                perror("init_socket");
        } else {
                memcpy(op->src_file, argv[2], strlen(argv[2]));
                memcpy(op->dst_file, argv[3], strlen(argv[3]));
                op->read_write = atoi(argv[4]);
                op->magic = START_EXIT;
        }
        if(sock < 0) {
                /* null */
        } else if(safe_send(sock, op, sizeof(*op), 0) != sizeof(*op)) {
                perror("send");
        } else {
                switch(op->read_write)
                {
                case READ_OP:
                        printf("client read file:%s -> %s\n", op->src_file, op->dst_file);
                        client_read_file(sock, op);
                        break;
                case WRITE_OP:
                        printf("client write file:%s -> %s\n", op->src_file, op->dst_file);
                        client_write_file(sock, op);
                        break;
                default:
                        break;
                }
        }
        if(!op) {
                /* null */
        } else {
                free(op);
        }
        if(sock < 0) {
                /* null */
        } else {
                close(sock);
        }
        return 0;
}

void client_read_file(int client, struct trans_op *op)
{
        // server send to -> client
        __write(client, op, op->dst_file);
}
void client_write_file(int client, struct trans_op *op)
{
        // client send to -> server
        __read(client, op, op->src_file);
}

文件读写实现cs.c

#define READ_WRITE_END 0xBB
#define START_EXIT 0xCC
#define SERVICE_PORT 1234
#define WRITE_OP 1
#define READ_OP 0
struct trans_op
{
        uint8_t magic;
        uint8_t read_write;//0:READ_OP 1:WRITE_OP
        uint32_t size;
        char src_file[256];
        char dst_file[256];
        char buffer[4096 - 8 - 512];
};
void client_read_file(int client, struct trans_op *op);
void client_write_file(int client, struct trans_op *op);


ssize_t safe_recv(int sockfd, void *buf, size_t len, int flags)
{
        ssize_t res = 0;
        size_t expect = 0;

        do {
                res = recv(sockfd, (char *)buf + expect, len - expect, flags);
                if(res == -1) {
                        break;
                } else if(res == 0) {
                        break;
                } else {
                        expect += res;
                }
        } while(expect != len);
        if(res == -1) {
                /* null */
        } else {
                res = expect;
        }
        return res;
}

ssize_t safe_send(int sockfd, const void *buf, size_t len, int flags)
{
        ssize_t res = 0;
        size_t expect = 0;

        do {
                res = send(sockfd, (char *)buf + expect, len - expect, flags);
                if(res == -1) {
                        break;
                } else if(res == 0) {
                        break;
                } else {
                        expect += res;
                }
        } while(expect != len);
        if(res == -1) {
                /* null */
        } else {
                res = expect;
        }
        return res;
}

ssize_t safe_write(int fd, const void *buf, size_t count)
{
        ssize_t res = 0;
        size_t expect = 0;

        do {
                res = write(fd, (char *)buf + expect, count - expect);
                if(res == -1) {
                        break;
                } else if(res == 0) {
                        break;
                } else {
                        expect += res;
                }
        } while(expect != count);
        if(res == -1) {
                /* null */
        } else {
                res = expect;
        }
        return res;

}
ssize_t safe_read(int fd, void *buf, size_t count)
{
        ssize_t res = 0;
        size_t expect = 0;

        do {
                res = read(fd, (char *)buf + expect, count - expect);
                if(res == -1) {
                        break;
                } else if(res == 0) {
                        break;
                } else {
                        expect += res;
                }
        } while(expect != count);
        if(res == -1) {
                /* null */
        } else {
                res = expect;
        }
        return res;

}

void __write (int client, struct trans_op *op, char *filename)
{
        int fd = open(filename, O_CREAT | O_WRONLY, 0777);
        ssize_t total = 0;

        printf("write %s\n", filename);
        if(fd < 0) {
                perror("open");
        }
        else {
                while(1) {
                        memset(op, 0, sizeof(*op));
                        if(safe_recv(client, op, sizeof(*op), 0) != sizeof(*op)) {
                                break;
                        } else if(op->magic == READ_WRITE_END) {
                                printf("magic is bb exit.\n");
                                break;
                        } else if(safe_write(fd, op->buffer, op->size) != op->size) {
                                perror("safe_write");
                                break;
                        } else {
                                total += op->size;
                        }
                }
                printf("toatl = %ld\n", total);
                close(fd);
        }

        /* check return code */
        if(op->magic != READ_WRITE_END || op->size != total) {
                printf("end fail\n");
        } else {
                printf("end success\n");
        }
        /* replay */
        op->magic = START_EXIT;
        op->size = total;
        safe_send(client, op, sizeof(*op), 0);
}
void __read(int client, struct trans_op *op, char *filename)
{
        int fd = open(filename, O_RDONLY, 0777);
        ssize_t total = 0;

        printf("read %s\n", filename);
        if(fd < 0) {
                perror("open");
        }
        else {
                while(1) {
                        memset(op, 0, sizeof(*op));
                        if((op->size = safe_read(fd, op->buffer, sizeof(op->buffer))) < 0) {
                                perror("read error");
                                break;
                        } else if(op->size == 0) {
                                /* read end */
                                break;
                        } else if(safe_send(client, op, sizeof(*op),0) != sizeof(*op)) {
                                perror("send error");
                                break;
                        } else {
                                total += op->size;
                        }
                }
                /* relply */
                op->magic = READ_WRITE_END;
                op->size = total;
                if(safe_send(client, op, sizeof(*op), 0) == sizeof(*op)) {
                        /* null */
                } else {
                        perror("safe_send");
                }
                printf("toatl = %ld\n", total);
                close(fd);
        }
        /* check return code */
        safe_recv(client, op, sizeof(*op), 0);
        if(op->magic != START_EXIT || op->size != total) {
                printf("end fail, op->magic,op->size=%d,%d\n", op->magic, op->size);
        } else {
                printf("end success\n");
        }
}

<完> 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值