#pragma once
#include <fun.h> //包含各种需要用到的标准库和Linux库和一个检查返回值的宏定义,省略
#define FILENAME "test.txt"
//子进程状态信息数据结构
typedef struct{
int pid;//进程号
int fd; //通信套接字
int busy;//进程状态,0代表阻塞,1代表运行,-1代表死亡
}pro_data;
// 用来传输文件的数据结构
typedef struct{
int len;//控制信息,提示接下来的字节长度
char p[1024];//真正的数据信息
}Train_t;
//创建num子进程,传出参数p保存各个子进程的状态信息队列
int fork_child(int num,pro_data * p);
//向传入的套接字传输文件
int transp(int);
//子进程工作函数,传入参数是其与父进程通信的套接字接口
int work(int);
//传送文件描述符,第一个参数是目的描述符,第二个参数是要传送的文件描述符
int sendFD(int,int);
//接收文件描述符,第一个参数是接收信息的套接字描述符,第二个参数是传出参数,传出接收的文件描述符
int recvFD(int,int *);
客户端
#include <fun.h>
#include "pool.h"intmain(int args,char*argv[]){
struct winsize wsize;ioctl(STDOUT_FILENO, TIOCGWINSZ,&wsize);ARG_CHECK(args,3);int sfd =tcp_connect(argv[1],atoi(argv[2]));RET_CHECK(sfd,-1,"client tcp connetc");printf("successfully connetc server.\n");
Train_t train;int ret;//get filename and create fileint len;
ret =recv(sfd,&len,4,0);RET_CHECK(ret,-1,"服务器已满负荷,请稍候再试");
ret =recv(sfd,train.p,len,0);RET_CHECK(ret,-1,"getfilename");
train.p[ret]='\0';int fd =open(train.p,O_RDWR|O_CREAT,0666);if(fd==-1){
printf("文件创建失败,可能存在同名文件!client exit.\n");close(sfd);return0;}//get size of file int size;
ret =recv(sfd,&size,sizeof(int),0);RET_CHECK(fd,-1,"recv");printf("the size of file is %d\n",size);printf("start downloading file %s\n",train.p);int getsize =0;while(1){
ret =recv(sfd,&len,4,MSG_WAITALL);RET_CHECK(ret,-1,"getlen");if(len ==0&& ret ==4){
printf("\r");printf(">进度:%5.2f%s 已下载:%d",(double)getsize/size*100,"%",getsize);for(int i =0;i<(getsize/size)*(wsize.ws_row-35);i++){
printf("-");}printf(">\ndownload is finished\n");close(fd);close(sfd);return