博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
上传文件块client实现
阅读量:5758 次
发布时间:2019-06-18

本文共 4631 字,大约阅读时间需要 15 分钟。

首先由内容阻止所有文件(块大小的约束),然后对于每一个chunk构造单独的一个UDP 数据报进行传输,在应用层的開始是自己定义的包头,有块号,块长度,块指纹等元数据信息,这些信息便于接收端可以按序正确接收。

/*--vonzhou ---this project is to upload file after chunking using     rabin fingerprint, here use UDP so that every packet nodelay.    but we need to ensure the reliability.*/#include "global.h"#define SERV_PORT 2500typedef struct {        unsigned char fp[20];        int chunk_id;        short flags;        short chunk_len; // The max is 32767 enough        char data[MAX_CHUNK_SIZE];}TransferUnit;// some flags for this chunk transfered.enum{        CHUNK_NEED_DEDU = 0x0001,   // need deduplication        CHUNK_OTHER = 0x0002      // other for extension};FileInfo *fi;int sendUDP(FileInfo *fi,int sockfd,struct sockaddr *pservaddr,socklen_t servlen){    char buf[sizeof(TransferUnit)];    fd_set wrset;    struct timeval tv;    int rlen,wlen, len = 1;    int fd;    int ret;    int i,j;    FingerChunk *p;    TransferUnit unit;    //connect to server    if(connect(sockfd,(struct sockaddr *)pservaddr,servlen) == -1)        err_quit("connet error");    else        printf("connect server ok!\n");    fd = open(fi->file_path, O_RDONLY);    if(fd==-1)        err_quit("fopen error %s\n",strerror(errno));    // begin to transfer the file to the server;                i=0;    p = fi->first;    while(1){        tv.tv_sec = 1;// tell select to wait 1 second;        tv.tv_usec = 0;        FD_ZERO(&wrset);        FD_SET(sockfd,&wrset);        // wait for the socket can write                ret = select(sockfd+1,NULL,&wrset,NULL,&tv);        if(ret == -1)            err_quit("select error %s\n",strerror(errno));        else if(ret==0){            printf("select timeout,continue circle\n");            continue;        }        //prepare for writing the socket                memset(&unit, 0, sizeof(unit));        if(FD_ISSET(sockfd,&wrset)){            /* we should first transfer some medadata,like filename,filter feature vector,            *FIXME: file fingerprint to controller?

to make a packetin, *here just let the fp = 20 1s */ if(i == 0){ for(j=0;j<20;j++) unit.fp[j] = 0xff; unit.chunk_id = 0; //need not dedu unit.chunk_len = strlen(fi->file_path); wlen = write(sockfd, &unit, 28 + strlen(fi->file_path)); if(wlen != (28 + strlen(fi->file_path))) err_quit("write data to sockfd error:%s\n",strerror(errno)); memset(&unit, 0, sizeof(unit)); } if(p != NULL) len = p->chunklen; // the last read , p is null, so cannnot use p->chu rlen = read(fd, unit.data, len); if(rlen < 0) err_quit("fread data error %s\n",strerror(errno)); else if(rlen==0){ //indicate the transfer completed for(j=0;j<20;j++) unit.fp[j] = 0xff; unit.chunk_id = 0; //need not dedu unit.chunk_len = 3; strncpy(unit.data,"end", 3); wlen = write(sockfd,&unit,28 + 3); if(wlen !=31) err_quit("write end flag error:%s\n",strerror(errno)); printf("File %s Transfer Success!\n", fi->file_path); close(fd); return 0; } // construct this tranfer unit we cannot before read //bcos the following p pointer used. for(j=0; j< 20;j++) unit.fp[j] = p->chunk_hash[j];// 20B fingerprint; unit.chunk_id = i; // 4B chunk ID unit.chunk_len = p->chunklen; unit.flags = CHUNK_NEED_DEDU; //write to socket wlen = write(sockfd, &unit, 28+p->chunklen); if(wlen != (rlen + 28)) err_quit("write data to sockfd error:%s\n",strerror(errno)); i++; p = p->next; memset(&unit, 0, sizeof(unit)); usleep(500); printf("The %d times read\n",i); } }// end while(1) } int main(int argc ,char *argv[]) { char *fh; struct sysinfo s_info; long time1,time2; int error1,error2; int sockfd; struct stat fsize; struct sockaddr_in servaddr; error1= sysinfo(&s_info); time1 = s_info.uptime; int r; // FileInfo *fi; fi = file_new(); if(argc != 3) err_quit("useage:udpclient<IPaddress>;\n"); bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family= AF_INET; servaddr.sin_port = htons(SERV_PORT); if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr) <= 0) err_quit("[%s]is not a valid IPaddress\n",argv[1]); sockfd =socket(AF_INET,SOCK_DGRAM,0); r = fcntl(sockfd, F_GETFL, 0); fcntl(sockfd, F_SETFL, r & ~O_NONBLOCK); // chunking file strcpy(fi->file_path, argv[2]); chunk_file(fi); printf("File size : %lld\n",fi->file_size); printf("Chunk Num : %d\n",fi->chunknum); sendUDP(fi, sockfd, (struct sockaddr *)&servaddr,sizeof(servaddr)); close(sockfd); fprintf(stderr,"ServerIP:\t%s\n",argv[1]); if(stat(argv[2],&fsize) == -1) perror("failed to get fiel statusi\n"); else fprintf(stderr,"file name:\t%s\nfile size:\t%dK\n",argv[2],fsize.st_size/1024); error2=sysinfo(&s_info); time2 = s_info.uptime; printf("tranfice file time =%ld seconds\n",(time2-time1)); }

转载请注明出处:

版权声明:本文博客原创文章,博客,未经同意,不得转载。

你可能感兴趣的文章
例题10-2 UVa12169 Disgruntled Judge(拓展欧几里德)
查看>>
JS 原生ajax写法
查看>>
Composer管理PHP依赖关系
查看>>
React.js学习笔记之JSX解读
查看>>
我所了解的Libevent和SEDA架构
查看>>
Socket编程问题小记
查看>>
基于Flask-Angular的项目组网架构与部署
查看>>
一张图道尽程序员的出路
查看>>
redis 常用命令
查看>>
LVS+Keepalived高可用负载均衡集群架构
查看>>
烂泥:kvm安装windows系统蓝屏
查看>>
iPhone开发面试题--葵花宝典
查看>>
EdbMails Convert EDB to PST
查看>>
POJ 2184
查看>>
大话 程序猿 眼里的 接口
查看>>
struts2用了哪几种模式
查看>>
replace函数结合正则表达式实现转化成驼峰与转化成连接字符串的方法
查看>>
ubuntu 初学常用命令
查看>>
WCF客户端与服务端通信简单入门教程
查看>>
android 资源种类及使用
查看>>