1. 程式人生 > >Linux C TCPSocket 傳輸檔案簡單例項-多執行緒實現

Linux C TCPSocket 傳輸檔案簡單例項-多執行緒實現

在Linux下使用C語言TCPSocket實現簡單檔案傳輸,包括客戶端和伺服器端,其中,伺服器端使用多執行緒實現同時接收多個客戶端傳送的檔案。

傳送檔案內容之前,首先需要將檔名和長度資訊傳送到伺服器,為了便於區分,採用傳送結構體的方式,設定標誌位,1標識資料域為檔名,2標識資料域為檔案內容,3標識傳送結束,4標識傳送檔案長度。這樣便可區分發送的內容。

伺服器端程式碼如下:

/*多執行緒實現接收多個客戶端的檔案*/
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #define PORT 8887 #define BUFF_SIZE 1024 typedef struct{ char type; char data[BUFF_SIZE]; }m_package; void* process_client(); int main(){ int ss = create_tcp_server(PORT); if(-1 == ss) exit
(-1); while(1){ //接受客戶端連線 socklen_t addrlen = sizeof(struct sockaddr); struct sockaddr_in client_addr; //客戶端地址結構 int client_sock = accept(ss, (struct sockaddr*)&client_addr, &addrlen); if(client_sock < 0){ printf("accept error\n"); } printf
("accept success\n"); pthread_t pid; if(pthread_create(&pid, NULL, process_client, &client_sock) < 0){ printf("pthread_create error\n"); } } } //處理客戶端程式 void *process_client(void *arg){ int size = 0, fd, count = 0, sockid = *(int*)arg; m_package pac; long total = 0, cur = 0; //迴圈接收檔案 while(1) { memset(&pac, 0, sizeof(pac)); size = read(sockid, &pac, sizeof(pac)); if(size > 0){ if (pac.type == 1){ fd = open(pac.data, O_CREAT|O_WRONLY, 0777); if(-1 == fd){ printf("open file error!\n"); continue; } count = total = cur = 0; } else if (pac.type == 2){ cur += write(fd, pac.data, strlen(pac.data)); if(count++ % 5000 == 0){ printf("recv from client < %d > : %.01lf\%\n", sockid, cur * 100.0 / total); count = 0; } } else if (pac.type == 3){ printf("recv from client < %d > : 100.0\%\n", sockid); printf("recv success\n"); close(fd); } else if(pac.type == 4){//檔案長度 total = strtol(pac.data, NULL, 10); printf("%ld\n", total); } }else{ printf("client disconnected\n"); close(sockid); break; } } return 0; }
#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>

#define PORT 8888
#define BUFF_SIZE 1024

typedef struct{
    char type;
    char data[BUFF_SIZE];
}m_package;

int main(){
    //建立連線
    int sock_fd = connect_tcp("192.168.134.188", PORT);
    if(-1 == sock_fd)
        return -1;

    m_package pac;
    int fd, cur = 0, count = 0;
    long filesize = 0;
    while(1){
        //開啟檔案
        memset(&pac, 0, sizeof(pac));
        pac.type = 1;
        // strcpy(pac.data, "/home/SKZH/a.txt");
        scanf("%s", pac.data);
        //獲取檔案資訊
        struct stat sfile;
        stat(pac.data, &sfile );
        filesize = sfile.st_size;
        time_t t;
        long begin = time(&t);
        cur = count = 0;

        fd = open(pac.data, O_RDONLY);
        if(-1 == fd){
            printf("file open error\n");
            continue;
        }
        //讀取檔案併發送
        //傳送檔名
        strcpy(pac.data, strrchr(pac.data, '/') + 1);
        write(sock_fd, &pac, sizeof(pac));
        memset(&pac, 0, sizeof(pac));

        //傳送檔案長度
        pac.type = 4;
        sprintf(pac.data,"%ld",filesize);
        write(sock_fd, &pac, sizeof(pac));
        memset(&pac, 0, sizeof(pac));

        int read_len = 0;
        while((read_len = read(fd, pac.data, BUFF_SIZE)) > 0){
            pac.type = 2;
            write(sock_fd, &pac, sizeof(pac));
            memset(&pac, 0, sizeof(pac));
            cur += read_len;
            if(count++ % 5000 == 0){
                count = 0;
                printf("send to server : %.1lf\%\n", cur * 100.0 / filesize);
            }
        }

        //傳送結束標記
        memset(&pac, 3, sizeof(pac));
        write(sock_fd, &pac, BUFF_SIZE + 1);
        close(fd);

        printf("send to server : 100.0\%\n");
        printf("file size : %d B\n", filesize);
        printf("time : %ld ms\n", time(&t) - begin);
        printf("send file success\n");
        printf("------------------------\n");
    }
    close(sock_fd);
}