Linux-C下C/S架构实例,实现文件传输功能

/*server_func.h*/

#ifndef SERVER_H
#define SERVER_H

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include 

#define MAX_CON 10
#define MAX_SIZE 1024
#define CMD_EXIT "exit"
#define CMD_DOWNLOAD_FILE "df"

typedef enum  tagCmdID
{
    CMD_INVALID = -1,
    CMD_FILE_EXIST,
    CMD_FILE_NOT_EXIST
}E_CMD_ID;

typedef struct tagClientCom
{
    E_CMD_ID cmd_id;
    long length;
}T_CLIENT_COM_HEADER;

typedef struct
{
    int sfd;
    int cfd;
    char filename[128];
}tcp_info;

int tcp_init(const char* ip, int port);
int tcp_accept(int sfd);
void * send_file(void * arg);
void * pthread_recv(void *arg);
void signalhandler(void);

#endif

/*server_func.c*/

#include "server_func.h"
int tcp_init(const char* ip, int port)  //用于初始化
{
    int on = 1;
    int sfd = socket(AF_INET, SOCK_STREAM, 0); //首先建立一个Socket,向系统申请
    if(sfd == -1)
    {
        printf("socket error: %s\n", strerror(errno));

        return -1;
    }

    int ret = setsockopt( sfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) );
    if(ret < 0)
    {
        printf("setsockopt error: %s", strerror(errno));
    }

    struct sockaddr_in serveraddr;
    memset( &serveraddr, 0, sizeof(struct sockaddr) ); 
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port); 
    serveraddr.sin_addr.s_addr = INADDR_ANY; //或者INADDR_ANY
    
    if(bind(sfd, (struct sockaddr*)&serveraddr, sizeof(struct sockaddr)) == -1)
    {
        printf("Bind error: %s\n", strerror(errno));
        close(sfd);
        
        return -1;
    }
    
    if(listen(sfd, MAX_CON) == -1)  //监听它 最大连接数为10
    {
        printf("Listen error: %s\n", strerror(errno));
        close(sfd);
        
        return -1;
    }
    
    return sfd;
}

int tcp_accept(int sfd)
{
    struct sockaddr_in clientaddr;
    int addrlen = sizeof(struct sockaddr);
    int new_fd = accept(sfd, (struct sockaddr*)&clientaddr, &addrlen);
    
    memset(&clientaddr, 0, addrlen);
    
    if(new_fd == -1)
    {
        printf("accept error: %s\n", strerror(errno));
        sleep(1);
        return -1;
    }
    printf("Client%d(%s %d) success connect...\n", new_fd, inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
    
    return new_fd;
}

void * send_file(void * arg)
{
    int needSend = sizeof(T_CLIENT_COM_HEADER);
    char *head = (char*)malloc(needSend);
    char buffer[MAX_SIZE];
    T_CLIENT_COM_HEADER *com = (T_CLIENT_COM_HEADER*)malloc(sizeof(T_CLIENT_COM_HEADER)); 
    tcp_info *client_info;
    
    client_info = ( tcp_info *)arg;
    com->length = needSend;
    memset(buffer, 0, sizeof(buffer));
    
    if(access(client_info->filename, F_OK) >= 0)
    {
        FILE *fp = fopen(client_info->filename, "r");
        fseek(fp, 0L, SEEK_END);  
        long file_size = ftell(fp);
        
        rewind(fp);
        
        com->length += file_size;
        com->cmd_id = CMD_FILE_EXIST;
        
        memcpy(head, com, needSend);
        
        int sendlength = send(client_info->cfd, head, needSend, 0);
        printf("head->cmd_id = %d, head->length = %ld\n", com->cmd_id, com->length);
        do
        {
            int file_block_length = fread(buffer, sizeof(char), MAX_SIZE, fp);
            
            int len = send(client_info->cfd, buffer, file_block_length, 0);

            if(file_block_length <= 0)
            {
                break;
            }
            bzero(buffer, sizeof(buffer));  
        }while(1);

        fclose(fp);
        printf("File:\t%s \nTransfer Finished!\n", client_info->filename);  
        
    }
    else
    {
        com->cmd_id = CMD_FILE_NOT_EXIST;
        memcpy(head, com, needSend);
        int sendlength = send(client_info->cfd, head, needSend, 0);
    }
}



void* pthread_recv(void *arg)
{
    char buf[128] = {0};
    tcp_info *client_info;
    
    client_info = ( tcp_info *)arg;
    memset(buf, 0, sizeof(buf));

    while(1)
    {
        char commond[64];
        char filename[128];
        int ret = recv(client_info->cfd, buf, sizeof(buf), 0 );

        if (ret < 0)
        {
            printf("receive error: %s\n", strerror(errno));
            
            break;
        }
        else if(ret == 0)
        {
            printf("Client%d(Exception) exit!\n", client_info->cfd);
            break;
        }

        if(0 == strcmp(buf, CMD_EXIT))
        {
            printf("Client%d exit!\n", client_info->cfd);
            break;
        }
        
        if((sscanf(buf, "%s %s", commond, filename) != 0) && (0 == strcmp(commond, CMD_DOWNLOAD_FILE)))
        {
            pthread_t pid;
            int ret;
            int length = 0;
            
            strcpy(client_info->filename, filename);
            
            ret = pthread_create(&pid, NULL, send_file, (void*)client_info);
            
            continue;
        }
        
        printf("Client%d: %s\n", client_info->cfd, buf);
    }
    close(client_info->cfd);
    free(client_info);
    pthread_exit(NULL);
}

void signalhandler(void)  
{  
    sigset_t sigSet;  
    sigemptyset(&sigSet);  
    sigaddset(&sigSet,SIGINT);  
    sigaddset(&sigSet,SIGQUIT);  
    sigaddset(&sigSet,SIGPIPE);  
    sigprocmask(SIG_BLOCK,&sigSet,NULL);      
}  

/*server.c*/

#include "server_func.h"

int main(int argc,char **argv)
{
    int ret_send;
    int ret_recv;

    int sfd;
    int cfd;
    
    sfd = tcp_init("192.168.20.217", 1234);
    if(-1 == sfd)
    {
        return 0;    }

    signalhandler();
    
    do
    {
        
        pthread_t id2;
        
        tcp_info *info;
        
        cfd = tcp_accept(sfd);
        if(cfd < 0)
        {
            continue;
        }
        info = (tcp_info*)malloc(sizeof(tcp_info));
        
        info->sfd = sfd;
        info->cfd = cfd;
        
        ret_recv = pthread_create(&id2, NULL, pthread_recv, (void*)info); 
        if(ret_recv != 0)
        {
            printf("create pthread error!\n");
        }

    }while(1);

    close(cfd);
    close(sfd);

    return 0;
}

/*client_func.h*/

#ifndef CLIENT_H
#define CLIENT_H

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define MAX_SIZE 1024
#define CMD_EXIT "exit"
#define CMD_DOWNLOAD_FILE "df"

typedef enum  tagCmdID
{
    CMD_INVALID = -1,
    CMD_FILE_EXIST,
    CMD_FILE_NOT_EXIST
}E_CMD_ID;

typedef struct tagClientCom
{
    E_CMD_ID cmd_id;
    long length;
}T_CLIENT_COM_HEADER;

typedef struct
{
    int cfd;
    char filename[128];
    
}file_information;

int tcp_connect(const char* ip, int port);
void* recv_file(void *arg);
void* pthread_send(void *arg);

#endif

/*client_func.c*/

#include "client_func.h"
int tcp_connect(const char* ip, int port)
{
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sfd == -1)
    {
        printf("socket error: %s", strerror(errno));

        return -1;
    }
    
    struct sockaddr_in serveraddr;
    memset(&serveraddr, 0, sizeof(struct sockaddr) );
    
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(port);
    serveraddr.sin_addr.s_addr = inet_addr(ip);

    if(connect(sfd, (struct sockaddr*) &serveraddr, sizeof(struct sockaddr)) == -1 )
    {
        printf("connect error: %s", strerror(errno));
        close(sfd); 

        return -1;
    }

    return sfd;
}

void* recv_file(void *arg)
{
    int needRecv = sizeof(T_CLIENT_COM_HEADER);
    int length = 0;
    long pos = 0; 
    
    char *head = (char*)malloc(needRecv);
    char buffer[MAX_SIZE];
    
    file_information *file_info;
    T_CLIENT_COM_HEADER *myNode = (T_CLIENT_COM_HEADER*)malloc(sizeof(T_CLIENT_COM_HEADER));
    
    file_info = ( file_information *)arg;
    char *filename = basename(file_info->filename);
    memset(&buffer, 0, MAX_SIZE);
    
    while(pos < needRecv)
    {
        length = recv(file_info->cfd, head+pos, needRecv, 0);
        if (length < 0)
        {
            printf("Server Recieve Data Failed!\n");
            break;
        }
        pos += length;
    }
    memcpy(myNode,head,needRecv);
    if(myNode->cmd_id == CMD_FILE_EXIST)
    {
        printf("File %s is sending...\n", filename);
        filename = NULL;
        FILE *fp = fopen(file_info->filename, "w");  
        length = 0;
        pos = 0;
        
        if (fp == NULL)  
        {
            printf("File:\t%s Can Not Open To Write!\n", file_info->filename);  
            return;
        }

        while(pos < myNode->length - needRecv)
        {
            int write_length;
            length = recv(file_info->cfd, buffer, MAX_SIZE, 0);
            if (length < 0)
            {
                printf("Recieve Data From Server Failed!\n");  
                break;
            }
            
            pos += length;
            write_length = fwrite(buffer, sizeof(char), length, fp);  
            
            if (write_length < length)
            {
                printf("File:\t%s Write Failed!\n", file_info->filename);  
                break;  
            }
            bzero(buffer, MAX_SIZE);  
        }
        
        printf("Recieve File: %s\tFrom Server Finished!\n", file_info->filename);  
  
        fclose(fp);
    }
    else if(myNode->cmd_id == CMD_FILE_NOT_EXIST)
    {
        printf("File %s is not exist!\n", file_info->filename);
    }
    free(head);
    free(myNode);
}

void* pthread_send(void *arg)
{
    int *temp;
    char buf[128];

    memset(buf, 0, sizeof(buf));
    temp = (int *)arg; 
    
    while(1)
    {
        char commond[64];
        char filename[128];
        char save_path[128];
        int arg_cont;
        gets(buf);

        
        
        if(-1 == send(*temp, buf, sizeof(buf), 0))
        {
            printf("send error: %s", strerror(errno));
            close(*temp);

            return;
        }
        
        if(0 == strcmp(buf, CMD_EXIT))
        {
            break;
        }

        if(((arg_cont = sscanf(buf, "%s %s %s", commond, filename, save_path)) != 0) && (0 == strcmp(commond, CMD_DOWNLOAD_FILE)))
        {
            if(arg_cont != 3)
            {
                printf("parameter error!\n");
                continue;
            }
            file_information *file_info;
            pthread_t pid;
            int ret;
            
            file_info = (file_information *)malloc(sizeof(file_information));
            memset(file_info, 0, sizeof(file_information));
            
            strcpy(file_info->filename, save_path);
            file_info->cfd = *temp;
            
            ret = pthread_create(&pid, NULL, (void*)recv_file, (void*)file_info);
            if(ret != 0)
            {
                printf("create pthread error!\n");
            }
        }
        
    }
    close(*temp);
    pthread_exit(NULL);
}

/*client.c*/

#include "client_func.h"

int main(int argc,char **argv)
{
    int ret_send;

    pthread_t id1;
    
    int sfd = tcp_connect("192.168.20.217", 1234);

    int *p_sfd = &sfd;
    ret_send = pthread_create(&id1, NULL, (void*)pthread_send, (void*)p_sfd);
    if(ret_send != 0)
    {
        printf("create pthread error!\n");
    }
    else
    {
        pthread_join(id1, NULL);
    }

    close(sfd);

    return 0;
}



服务器端:

Linux-C下C/S架构实例,实现文件传输功能_第1张图片

客户端1:

Linux-C下C/S架构实例,实现文件传输功能_第2张图片

客户端2:

Linux-C下C/S架构实例,实现文件传输功能_第3张图片

这是一个demo仅用来学习~

下面是传输文件运行截图,可以用来传输比较大的文件,试过传输3G多的文件:

Linux-C下C/S架构实例,实现文件传输功能_第4张图片

Linux-C下C/S架构实例,实现文件传输功能_第5张图片

后面加上makefile:

.PHONY : clean server

#server: client server.c
#	gcc server.c -o server -lpthread
#client: client.c
#	gcc client.c -o client -lpthread
#clean:
#	pkill -9 server
#	pkill -9 client
#	rm server client
	
GCCTV = arm-linux-androideabi-gcc
GCC = gcc
object = server_func.o server.o client_func.o client.o
LFLAG = -lpthread
#LFLAG = -pie -fPIE

server : server.o server_func.o client
	$(GCC) -o server server.o server_func.o $(LFLAG)
server.o : server.c
	$(GCC) -c server.c $(LFLAG)
server_func.o : server_func.c
	$(GCC) -c server_func.c $(LFLAG)

client : client.o client_func.o
	$(GCC) -o client client.o client_func.o -lpthread
client.o : client.c
	$(GCC) -c client.c -lpthread
client_func.o : client_func.c
	$(GCC) -c client_func.c -lpthread
	
clean:
	rm $(object)




你可能感兴趣的:(Linux-C)