1. 程式人生 > >網路傳輸檔案 -- 迴圈傳送檔案

網路傳輸檔案 -- 迴圈傳送檔案

fread

FILE *fopen(const char *path, const char *mode);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

size_t fwrite(const void *ptr, size_t size, size_t nmemb,
                     FILE *stream);

  •  
  • 第二個引數:型別,每個元素size個位元組
  • 第三個引數count是讀取的資料個數,資料大小為自己的第二個引數size的值。即讀取count個size大小的資料。
  • 返回值:

    • 正常:返回實際讀取到的元素個數
    • 檔案尾:return 0
    • 非正常:return 0。
  • 一般就用

    • char buffer[1024] = {‘\0’};
    • fread(buffer,1,sizeof(buffer),fp);

int open(const char *pathname, int flags, mode_t mode);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
  • fd:檔案描述符,用來指向要操作的檔案的檔案結構體
  • buf:一塊記憶體空間
  • count:希望讀取的位元組數
  • 返回值 
    • 正常:表示實際讀到的位元組數(字串結束符 ‘\0’不算)
    • 讀到檔案尾/套接字被被關閉:return 0
    • 發生錯誤:return -1
  • 一般就用
  • char buffer[1024] = {‘\0’};
  • read(fd,buffer,sizeof(buffer));

 

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.xxx.xxx";  

const char *file_name = "v06";

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, "wb");
    if (fp == NULL)
    {
        perror("fopen failed: ");
        return NULL;
    }

    return fp;
}

int main()
{
    int size, data_len;
    int flag;
    FILE* cli_fp;
    char buffer[BUFFER_SIZE];    // --接收資料長度, 後續根據開闢相應空間大小

    memset(buffer, 0, sizeof(buffer));

    // 初始化接收套接字
    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");

#if 0
    // 接收訊息頭
    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);
#endif
    // 接收正文
    //while(data_len = recv_message(sock_cli, buffer, BUFFER_SIZE))
    while(data_len = recv(sock_cli, buffer, BUFFER_SIZE, 0))
    {
        //printf("data recving.. buffer is %s\tdata_len = %d\n", buffer, data_len);
        printf("data recving.. data_len = %d\n", data_len);
        flag++;
        if (flag == 1)
            printf("data recving...\n");
        if (data_len == 0)
        {
            printf("receive err!\r\n");
            return -1;
        }
        int write_len = fwrite(buffer, sizeof(char), data_len, cli_fp);
        if (write_len > data_len)
        {
            printf("write data to file failed\n");
            return -1;
        }
        bzero(buffer, BUFFER_SIZE);
    }

    if (flag > 0)
        printf("transmit over.\n");
    else if(flag == 0)
        printf("transmit failed.\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_NAME = "V06";
//const char *FILE_NAME = "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_NAME, "rb");    // 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, len;
    char buffer[BUFFER_SIZE];
    memset(buffer, 0, sizeof(buffer));
    //char *send_buf;
#if 0
    // 開啟檔案,得到檔案大小
    size = get_file_size();
    printf("len: %d\n", size);
    
    // 開闢空間,存放升級檔案
    send_buf = malloc_save(size);
    printf("file text: %s\n", send_buf + sizeof(Data_t));
#endif

    // 初始化sockfd,並等待客戶端連線  
    ret = socket_handler();
    if (ret != 0)
    {
        printf("socket_handler failed\n");
        return -1;
    }
    // 開啟檔案
    FILE *fp = fopen(FILE_NAME, "rb");
    if (fp == NULL)
    {
        printf("the file was not open!\n");
        return -1;
    }

    printf("open file succ, And transmit data after 5s ..\n");
    sleep(5);
    // 傳送檔案
    /*while(!feof(fp))  // return !0  show file is eof*/
    /*{ */
        /*len = fread(buffer, 1, 1024, fp);*/
    while((len = fread(buffer, 1, 1024, fp)) > 0){
        //printf("len = %d\n", len);
        //if (send_message(conn, buffer, len) < 0)
        if (send(conn, buffer, len, 0) < 0)
        {
            printf("send_message failed\n");
            break;
        }
        bzero(buffer, BUFFER_SIZE);
    }
    printf("data transmit end!\n");

    fclose(fp);
    //free(send_buf);
    close(conn);
    close(server_sockfd);
    return 0;
}