網路傳輸檔案 -- 一次性得到檔案大小
阿新 • • 發佈:2018-11-08
client.c
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #define MYPORT 9191 #define BUFFER_SIZE 1024 //char* SERVER_IP = "XXX.XXX.X.XXX"; const char *file_name = "Recv_file"; int sock_cli; struct Data_s { int len; } __attribute__ ((__packed__)); typedef struct Data_s Data_t; int recv_message(int sockfd, char *buf, int len) { int count = 0, ret; for (; ;) { ret = recv(sockfd, buf + count, len - count, 0); if (ret == 0) { perror ("recv failed."); return -1; } count += ret; if (count == len) { break; } } return 0; } int init_sockfd() { int sockfd = socket(AF_INET,SOCK_STREAM, 0); return sockfd; } int connect_server() { ///定義sockaddr_in struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(MYPORT); ///伺服器埠 servaddr.sin_addr.s_addr = inet_addr(SERVER_IP); ///伺服器ip if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("connect"); return -1; } return 0; } FILE *open_new_file() { FILE *fp = fopen(file_name, "w"); if (fp == NULL) { perror("fopen failed: "); return NULL; } return fp; } int main() { int size; FILE* cli_fp; char buff[4]; // --接收資料長度, 後續根據開闢相應空間大小 memset(buff, 0, sizeof(buff)); // 初始化接收套接字 sock_cli = init_sockfd(); printf("connect %s:%d\n",SERVER_IP,MYPORT); // 初始化檔案指標 cli_fp = open_new_file(); // 連線伺服器,成功返回0,錯誤返回-1 if (connect_server() < 0) { printf("connect server failed\n"); return -1; } printf("connect server success\n"); // 接收訊息頭 recv_message(sock_cli, buff, sizeof(Data_t)); Data_t *mydata = (Data_t *)buff; // 根據頭訊息中長度,開闢相應大小空間 int len = ntohl(mydata->len); printf("trans data = %d\n", len); char *ar = (char *)malloc(len); memset(ar, 0, len); // 接收正文 int ret = recv_message(sock_cli, ar, len); if (ret < 0) { printf("recv_message failed.\n"); return -1; } // 寫入新檔案 fwrite(ar, 1, len, cli_fp); printf("write to file succ.\n"); free(ar); ar = NULL; fclose(cli_fp); close(sock_cli); return 0; }
server.c
#include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <fcntl.h> #include <sys/shm.h> #include <sys/stat.h> #include <fcntl.h> int server_sockfd; int conn; struct Data_s{ int length; } __attribute__ ((__packed__)); typedef struct Data_s Data_t; #define MYPORT 9191 #define QUEUE 20 #define BUFFER_SIZE 1024 //const char *FILE_PATH = "file_name"; const char *FILE_PATH = "1.c"; FILE *fp; int send_message(int sockfd, char *buf, int len) { int count = 0, ret; for (; ;) { ret = send(sockfd, buf + count, len - count, 0); if (ret == 0) { perror("send failed"); return -1; } count += ret; if (count == len) { break; } } return 0; } int socket_handler() { server_sockfd = socket(AF_INET,SOCK_STREAM, 0); int on = 1; int ret = setsockopt(server_sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)); if (ret < 0) { perror("setsockopt failed"); return -1; } ///定義sockaddr_in struct sockaddr_in server_sockaddr; server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(MYPORT); server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); ///bind,成功返回0,出錯返回-1 if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1) { perror("bind"); exit(1); } printf("listen port %d\n",MYPORT); ///listen,成功返回0,出錯返回-1 if(listen(server_sockfd,QUEUE) == -1) { perror("listen"); exit(1); } ///客戶端套接字 struct sockaddr_in client_addr; socklen_t length = sizeof(client_addr); printf("wait to client.. \n"); ///成功返回非負描述字,出錯返回-1 conn = accept(server_sockfd, (struct sockaddr*)&client_addr, &length); if(conn<0) { perror("connect"); exit(1); } printf("client connect succees!!\n"); return 0; } int get_file_size() { int size; fp = fopen(FILE_PATH, "r"); // rb 二進位制 rt 文字檔案 r+ 可讀可寫 if (fp == NULL) { perror("fopen failed: "); return -1; } fseek(fp, 0, SEEK_END); size = ftell(fp); rewind(fp); // 重定向到檔案開頭 return size; } char *malloc_save(int size) { // 存放檔案大小及內容 char *send_buf = (char *)malloc(sizeof(char) * size + sizeof(int)); memset(send_buf, 0, sizeof(send_buf)); Data_t *data = (Data_t *)send_buf; data->length = htonl(size); char *file_data = send_buf + sizeof(Data_t); fread(file_data, 1, size, fp); return send_buf; } int main() { int ret, size; char *send_buf; // 開啟檔案,得到檔案大小 size = get_file_size(); printf("len: %d\n", size); // 開闢空間,存放升級檔案 send_buf = malloc_save(size); printf("file text: %s\n", send_buf + sizeof(Data_t)); // 初始化sockfd,並等待客戶端連線 ret = socket_handler(); if (ret != 0) { printf("socket_handler failed\n"); return -1; } // 傳送檔案 while(1) { printf("Now to upload versiom, please input Y(y)\n"); if ('y' == getchar() || 'Y' == getchar()) { ret = send_message(conn, send_buf, size + sizeof(Data_t)); if (ret < 0){ printf("send_message failed\n"); break; } } printf("send client.. over\n"); } fclose(fp); free(send_buf); close(conn); close(server_sockfd); return 0; }