效果
服务端
./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"); } }
<完>