1. 程式人生 > >網路傳輸檔案 -- 一次性得到檔案大小

網路傳輸檔案 -- 一次性得到檔案大小

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;
}