在Linux下使用C语言TCPSocket实现简单文件传输,包括客户端和服务器端,其中,服务器端使用多线程实现同时接收多个客户端发送的文件。
发送文件内容之前,首先需要将文件名和长度信息发送到服务器,为了便于区分,采用发送结构体的方式,设置标志位,1标识数据域为文件名,2标识数据域为文件内容,3标识发送结束,4标识发送文件长度。这样便可区分发送的内容。
服务器端代码如下:
/*多线程实现接收多个客户端的文件*/
#include
#include
#include
#include
#include
#include
#include
#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;
}
服务器端对创建服务器代码进行了简单封装,需要在工程下添加相关的头文件和源文件,添加的代码见博客:http://blog.csdn.net/wanna_wsl/article/details/53712066
客户端对创建连接同样进行了简单封装,需引进封装的代码,同样参见博客
http://blog.csdn.net/wanna_wsl/article/details/53712066
客户端代码如下:
#include
#include
#include
#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);
}
源码下载地址:
https://github.com/Wushaoling/Linux-C-Socket/tree/master/TCP/TCP%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93