您的位置:首页 > 运维架构 > 网站架构

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

2016-11-09 10:25 676 查看
/*server_func.h*/

#ifndef SERVER_H
#define SERVER_H

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<signal.h>
#include<pthread.h>
#include <errno.h>

#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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <libgen.h>

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

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


服务器端:



客户端1:



客户端2:



这是一个demo仅用来学习~

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





后面加上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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息