Linux网络编程——进程池实现过程详解(3)
进程池如何提高文件传输效率
1、协议不变:小火车 服务器端:mmap+memcpy 客户端 recvCycle
tran_file.c
#include "function.h"
int tranFile(int newFd){
Train_t train;
int ret;
//发送文件名
train.dataLen = strlen(FILENAME);
strcpy(train.buf, FILENAME);
int fd = open(FILENAME, O_RDONLY);
ret = send(newFd, &train, 4 + train.dataLen, 0);
ERROR_CHECK(ret, -1, "send");
//发文件大小
struct stat buf;
fstat(fd, &buf);
train.dataLen = sizeof(buf.st_size);
memcpy(train.buf, &buf.st_size, train.dataLen);
ret = send(newFd, &train, 4 + train.dataLen, 0);
ERROR_CHECK(ret, -1, "send");
//发文件内容
off_t ptrPos = 0;
char *pMap = (char*)mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
train.dataLen = 1000;
//发送1000为内容单位的小火车
while(ptrPos + 1000 < buf.st_size){
memcpy(train.buf, pMap + ptrPos, train.dataLen);
ret = send(newFd, &train, 4 + train.dataLen, 0);
ERROR_CHECK(ret, -1, "send");
ptrPos += 1000;
}
//发送剩余部分
train.dataLen = buf.st_size - ptrPos;
memcpy(train.buf, pMap + ptrPos, train.dataLen);
ret = send(newFd, &train, 4 + train.dataLen, 0);
//发送结束标志
train.dataLen = 0;
ret = send(newFd, &train, 4, 0);
ERROR_CHECK(ret, -1, "send");
munmap(pMap, buf.st_size);
return 0;
}
2、协议改变:大火车 服务器端:mmap send 客户端 recvCycle/ mmap
tran_file.c
#include "function.h"
int tranFile(int newFd){
Train_t train;
int ret;
//发送文件名
train.dataLen = strlen(FILENAME);
strcpy(train.buf, FILENAME);
int fd = open(FILENAME, O_RDWR);
ret = send(newFd, &train, 4 + train.dataLen, 0);
ERROR_CHECK(ret, -1, "send");
//发文件大小
struct stat buf;
fstat(fd, &buf);
train.dataLen = sizeof(buf.st_size);
memcpy(train.buf, &buf.st_size, train.dataLen);
ret = send(newFd, &train, 4 + train.dataLen, 0);
ERROR_CHECK(ret, -1, "send");
//发文件内容
char *pMap = (char*)mmap(NULL, buf.st_size, PROT_READ, MAP_SHARED, fd, 0);
ret = send(newFd, pMap, buf.st_size, 0);
ERROR_CHECK(ret, -1, "send");
//发送结束标志
train.dataLen = 0;
ret = send(newFd, &train, 4, 0);
ERROR_CHECK(ret, -1, "send");
munmap(pMap, buf.st_size);
return 0;
}
client_reCycle.c
#include "function.h"
int main(int argc,char* argv[])
{
ARGS_CHECK(argc,3);
int socketFd;
socketFd=socket(AF_INET,SOCK_STREAM,0);
ERROR_CHECK(socketFd,-1,"socket");
struct sockaddr_in ser;
bzero(&ser,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);//点分十进制转为32位的网络字节序
int ret;
ret=connect(socketFd,(struct sockaddr*)&ser,sizeof(ser));
ERROR_CHECK(ret,-1,"connect");
printf("connect success\n");
int dataLen;
char buf[1000]={0};
//接收文件名
recvCycle(socketFd,&dataLen,4);
recvCycle(socketFd,buf,dataLen);
int fd;
fd=open(buf,O_CREAT|O_WRONLY,0666);
ERROR_CHECK(fd,-1,"open");
//接文件大小
off_t fileSize = 0, oldSize = 0, sliceSize;//文件大小off_t 长整型
off_t downLoadSize = 0;
recvCycle(socketFd,&dataLen,4);
recvCycle(socketFd,&fileSize,dataLen);
//接受文件内容
sliceSize = fileSize / 10000;
dataLen = 1000;
while(downLoadSize + 1000 < fileSize)
{
ret = recvCycle(socketFd,buf,dataLen);
if(-1 == ret){
printf("\n");
printf("server is update!\n");
break;
}
write(fd, buf, dataLen);
downLoadSize += dataLen;
if(downLoadSize - oldSize > sliceSize){
printf("\r%5.2f%%", (float)downLoadSize / fileSize * 100);
fflush(stdout);
oldSize = downLoadSize;
}
}
//剩余部分
dataLen = fileSize - downLoadSize;
ret = recvCycle(socketFd, buf, dataLen);
if(-1 == ret){
printf("recvCycle last error\n");
}
write(fd, buf, dataLen);
printf("\r100%% \n");
close(fd);
close(socketFd);
return 0;
}
client_mmap.c
#include "function.h"
int main(int argc,char* argv[])
{
ARGS_CHECK(argc,3);
int socketFd;
socketFd=socket(AF_INET,SOCK_STREAM,0);
ERROR_CHECK(socketFd,-1,"socket");
struct sockaddr_in ser;
bzero(&ser,sizeof(ser));
ser.sin_family=AF_INET;
ser.sin_port=htons(atoi(argv[2]));
ser.sin_addr.s_addr=inet_addr(argv[1]);//点分十进制转为32位的网络字节序
int ret;
ret=connect(socketFd,(struct sockaddr*)&ser,sizeof(ser));
ERROR_CHECK(ret,-1,"connect");
printf("connect success\n");
int dataLen;
char buf[1000]={0};
//接收文件名
recvCycle(socketFd,&dataLen,4);
recvCycle(socketFd,buf,dataLen);
int fd;
fd=open(buf,O_CREAT|O_RDWR,0666);
ERROR_CHECK(fd,-1,"open");
//接文件大小
off_t fileSize = 0;//文件大小off_t 长整型
recvCycle(socketFd,&dataLen,4);
recvCycle(socketFd,&fileSize,dataLen);
printf("finish1\n");
//接受文件内容
ftruncate(fd, fileSize);
char *pMap = (char*)mmap(NULL, fileSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
ERROR_CHECK(pMap, (char*)-1, "mmap");
ret = recvCycle(socketFd, pMap, fileSize);
ERROR_CHECK(ret, -1, "recvCycle");
printf("finish2\n");
ret = recvCycle(socketFd, buf, 4);
ERROR_CHECK(ret, -1, "recvCycle");
printf("finish3\n");
munmap(pMap, fileSize);
printf("\r100%% \n");
close(fd);
close(socketFd);
return 0;
}
3、协议:大火车 服务器端:sendfile 客户端 mmap
tran_file.c
#include "function.h"
int tranFile(int newFd){
Train_t train;
int ret;
//发送文件名
train.dataLen = strlen(FILENAME);
strcpy(train.buf, FILENAME);
int fd = open(FILENAME, O_RDWR);
ret = send(newFd, &train, 4 + train.dataLen, 0);
ERROR_CHECK(ret, -1, "send");
//发文件大小
struct stat buf;
fstat(fd, &buf);
train.dataLen = sizeof(buf.st_size);
memcpy(train.buf, &buf.st_size, train.dataLen);
ret = send(newFd, &train, 4 + train.dataLen, 0);
ERROR_CHECK(ret, -1, "send");
//发文件内容
ret = sendfile(newFd, fd, NULL, buf.st_size);
ERROR_CHECK(ret, -1, "sendfile");
//发送结束标志
train.dataLen = 0;
ret = send(newFd, &train, 4, 0);
ERROR_CHECK(ret, -1, "send");
return 0;
}
4、协议:大火车 服务器端:sendfile 客户端 splice/tee
client_splice