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
");
	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("
");
            printf("server is update!
");
            break;
        }
        write(fd, buf, dataLen);
        downLoadSize += dataLen;
        if(downLoadSize - oldSize > sliceSize){
            printf("
%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
");
    }
    write(fd, buf, dataLen);
    printf("
100%%         
");
	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
");
    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
");
    //接受文件内容
    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
");
    ret = recvCycle(socketFd, buf, 4);
    ERROR_CHECK(ret, -1, "recvCycle");
    printf("finish3
");
    munmap(pMap, fileSize);
    printf("
100%%         
");
    
    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