C++文件上传、下载工具
本文实例为大家分享了C++文件上传下载的实现代码,供大家参考,具体内容如下
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/timeb.h> #include<sys/ioctl.h> #include<string.h> #include<fcntl.h> #include<sys/wait.h> #include<sys/socket.h> #include<errno.h> #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<netinet/in.h> #include<netinet/tcp.h> #include<arpa/inet.h> #ifndef__TCPFILE_C__ #define__TCPFILE_C__ #include"libfunc.h" #include"vapi_log.h" #defineCMDHEAD6//通信报文头信息长度 #defineCMDINFO6//空值命令PUTGET #defineCMD #defineMAXKB16 #defineNCMD32 #defineNFILE128 //tcp通信命令行缓冲区 typedefstructtcpCmd{ intlen;//命令行长度 charcmd[NCMD+1];//命令行缓冲区 }tcpCmd; structtcpBuffer{ intrlen;//接收数据长度 intwlen;//发送数据长度 charrcvcmd[NCMD+1];//接收命令域数据 charsndcmd[NCMD+1];//接收命令域数据 tcpCmdrCmd;//接收缓冲区 tcpCmdsCmd;//发送缓冲区 charbuff[1024*MAXKB+64+1];//报文缓冲区,包含命令控制串和实际报文数据 }ncb; //////////////////////////////////////////////////////////////////////////////////////////////////// //// //根据报文头数据要求,接收一个通信数据。// //程序首先按照要求读取headlen长度的长度包数据,然后再次从网络上读取真正长度的数据包。// //// //数据接收函数分两次进行处理,返回数据sData中已经不再包含6位通信长度数据。// /////////////////////////////////////////////////////////////////////////////////////////////////// inttcp_readbuf(intheadlen,intsfd,char*sData,intMaxLen,intsTime) { intiRet=0; intleft_bytes,thisRead,sLen; char*ptr=sData; structtimevaltv; fd_setrfds; chartemp[NCMD+1]; tv.tv_sec=(long)sTime; tv.tv_usec=0; FD_ZERO(&rfds); FD_SET(sfd,&rfds); do{ iRet=select(sfd+1,&rfds,NULL,NULL,&tv); }while(iRet<0&&errno==EINTR); if(iRet==0){ wLog(LOGERROR,"tcp_readbufselect延时[%d]结束,faile[%d,%s]",sTime,errno,strerror(errno)); return-1; } //接受控制命令序列 memset(temp,0x00,sizeof(temp)); thisRead=read(sfd,temp,headlen); if(temp[0]=='0')sLen=atoi(temp); elsesLen=0; if(thisRead!=headlen&&sLen){ wLog(LOGERROR,"读取通信报文长度[%s]失败,faile[%d,%s]",temp,errno,strerror(errno)); return-1; } if(sLen<1||sLen>MaxLen){ if(sLen>MaxLen)wLog(LOGERROR,"报文长度[%s]错误,数据非法.",temp); return-1; } left_bytes=sLen; while(left_bytes>0){ if((thisRead=read(sfd,ptr,left_bytes))==0)break; if(thisRead<0){ if(errno==EINTR)continue; break; } left_bytes-=thisRead; ptr+=thisRead; } if(left_bytes&&ptr!=sData) wLog(LOGERROR,"[tcp_readbuf[%d]faile[%d,%s]",sLen,errno,strerror(errno)); /*数据没有处理完时,程序打印错误日志信息*/ return(sLen-left_bytes); } // //数据发送程序,在指定的延时内将指定长度的数据包发送到sfd上。 //发送数据需要将报文长度保存在sData中,发送长度比实际的报文多出长度域6字节 // inttcp_writebuf(intsfd,char*sData,intsLen,intsTime) { intiRet=0; intleft_bytes,thisWrite; char*ptr=sData; fd_setwfds; structtimevaltv; FD_ZERO(&wfds); FD_SET(sfd,&wfds); do{ iRet=select(sfd+1,NULL,&wfds,NULL,&tv); }while(iRet<0&&errno==EINTR); if(iRet==0){ wLog(LOGERROR,"tcp_writebufselect延时[%d]结束,faile[%d,%s]",sTime,errno,strerror(errno)); return-1; } //检查通信链路的写状态 left_bytes=sLen; while(left_bytes>0){ if((thisWrite=write(sfd,ptr,left_bytes))==0)break; if(thisWrite<0){ if(errno==EINTR)continue; break; } left_bytes-=thisWrite; ptr+=thisWrite; } //将数据发送到通信端口 if(left_bytes&&ptr!=sData) wLog(LOGERROR,"[tcp_sendbufleft_bytes[%d]faile[%d,%s]",left_bytes,errno,strerror(errno)); return(sLen-left_bytes); } //=============================客户端使用文件发送程序=================================//// //// //socket方式文件发送程序,根据输入的netinfo建立通信通道,然后按照以下要求发送文件// //PUT100发送文件基本信息// //PUT200发送文件内容,根据要求循环执行,......// //PUT300数据发送结束// //// //=======================================================================================//// intcli_put_sendFile(char*netinfo,char*localFile,char*remoteFile,intblockSize,inttimeout) { intsfd,fd; structstatsb; intiRet; intchkflg=0; intmaxBlk,blknum=0; longstart; longfsize; sfd=fd=-1; start=time(NULL); sfd=make_tcpConnect(netinfo); //申请socket描述符,使用connect()建立到服务器的连接通道 if(sfd<0){ wLog(LOGERROR,"建立到[%s]连接失败error[%d,%s]",netinfo,errno,strerror(errno)); return-4; } wLog(LOGINFO,"成功建立到[%s]发送通道[%d]",netinfo,sfd); fd=open(localFile,O_RDONLY); if(fd==-1){ wLog(LOGERROR,"本地文件[%s]打开失败error[%d,%s]",localFile,errno,strerror(errno)); close(sfd); return-3; } if(fstat(fd,&sb)<0){ wLog(LOGERROR,"取[%s]文件信息失败error[%d,%s]",localFile,errno,strerror(errno)); chkflg=-3; gotocli_put_sendFile_END; } fsize=sb.st_size; if(blockSize>1024*MAXKB)blockSize=1024*MAXKB; if(blockSize<1024)blockSize=1024; //显示本地文件的基本信息 wLog(LOGINFO,"成功打开本地文件[%s],size[%ld]",localFile,fsize); maxBlk=(int)((fsize)/blockSize); //计算本文件的最大传输次数 if(fsize%blockSize)maxBlk+=1; //不足整块的数据,需要按一块进行处理。 memset(&ncb,0x00,sizeof(structtcpBuffer)); //准备发送文件控制命令串,告诉对方准备发送文件的基础信息 ncb.wlen=snprintf(ncb.buff+25,sizeof(ncb.buff)-1,"%s:%010ld:%010d:%010d", remoteFile,fsize,blockSize,maxBlk); sprintf(ncb.sndcmd,"%06d%-16s%1s%2s",ncb.wlen+19,"PUT100FILEINFO","1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.wlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen,timeout); if(iRet!=ncb.wlen){ wLog(LOGERROR,"发送[%d][%s]失败error[%d,%s]",ncb.wlen,remoteFile,errno,strerror(errno)); chkflg=-2; gotocli_put_sendFile_END; } wLog(LOGINFO,"发送报文头[%d][%s]成功",ncb.wlen,ncb.buff); ncb.rlen=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(ncb.rlen!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程保存[%s]失败error[%d,%s]",remoteFile,errno,strerror(errno)); chkflg=-2; gotocli_put_sendFile_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); //循环将本地文件全部发送完毕 while(1){ blknum++; memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=read(fd,ncb.buff+25,blockSize); if(ncb.rlen<1)break;//本地文件已经发送结束 sprintf(ncb.sndcmd,"%06dPUT200BLK%07d%1s%2s",ncb.rlen+19,blknum,"1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.rlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.rlen,timeout); if(iRet!=ncb.rlen){ wLog(LOGERROR,"发送[%s]失败error[%d,%s]",ncb.sndcmd,errno,strerror(errno)); chkflg=-1; gotocli_put_sendFile_END; } if(blknum==1||blknum==maxBlk) wLog(LOGINFO,"发送数据[%d][%s]成功",ncb.rlen,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收[%s]失败error[%d,%s]",ncb.rcvcmd,errno,strerror(errno)); chkflg=-1; gotocli_put_sendFile_END; } } memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.wlen=snprintf(ncb.sndcmd,sizeof(ncb.sndcmd)-1,"%-16s%1s%2s","PUT300FILEOVER","1","00"); sprintf(ncb.buff,"%06d%s",ncb.wlen,ncb.sndcmd); iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen+6,timeout); if(iRet!=ncb.wlen+6){ wLog(LOGERROR,"发送FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_put_sendFile_END; } wLog(LOGINFO,"发送数据[%d][%s]成功",iRet,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_put_sendFile_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); wLog(LOGINFO,"传输[%s]-->[%s][%d]块,共[%ld]字节,耗时%ld秒\n\n",localFile,remoteFile, blknum,fsize,time(NULL)-start); cli_put_sendFile_END: if(sfd>0)close(sfd); if(fd>0)close(fd); //关闭本文描述符和通信连接通道描述符 returnchkflg; } //============================服务端使用文件传输程序=================================//// //// //socket文件接收服务程序,对收到的通信报文进行分析。// //在收到PUT100命令后,将该数据域中的文件名称与本地路径拼写得到完整的文件// //路径信息,打开本地文件。// //对PUT200数据域传输来的数据保存到本地文件中。// //收到PUT300命令,关闭本地文件,传输过程结束。// //// //文件传输服务端程序:// //sfd在accept()后获取的新的客户端连接通道描述符// //path准备保存本地文件的路径信息// //fileName根据接收报文中的文件名称与本地路径拼串而得到的返回文件信息// //timeout数据传输需要使用的延时参数// //// //返回数据:// //0----文件接收成功// //-2--文件无法创建,打开文件名称失败// //-1--文件内容内容保存失败// //======================================================================================//// intsrv_put_recvFile(intsfd,char*path,char*fileName,inttimeout) { intfd=-1; intblknum=0,maxBlk=0; chartfile[NFILE+1],bfile[NFILE+1]; char*ptr; longfsize=0; intchkflg=0; memset(tfile,0x00,sizeof(tfile)); while(1){ memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=tcp_readbuf(6,sfd,ncb.buff,sizeof(ncb.buff)-1,timeout); if(ncb.rlen<0)break; memcpy(ncb.sndcmd+6,ncb.buff,19); if(memcmp(ncb.buff,"PUT",3)){ wLog(LOGERROR,"接收命令序列[%s]错误,程序退出.",ncb.sndcmd+6); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-3; } switch(Nstr_int(ncb.buff+3,3)){ //获取PUT后面的命令控制字,下面分析该控制字进行工作 case100://开始接收文件,打开本地文件 wLog(LOGINFO,"接收管理报文[%s]成功",ncb.buff); //对于接收到的第一条命令,打印该控制命令的全部内容 ptr=strchr(ncb.buff,':'); if(ptr)memcpy(tfile,ncb.buff+19,ptr-(char*)ncb.buff-19); elsestrcpy(tfile,ncb.buff+19); //获取传输来的文件名称 ptr=strrchr(tfile,'/'); if(ptr)strcpy(bfile,ptr+1); elsestrcpy(bfile,tfile); //检查传输来文件名称中的路径信息,得到基本文件名称,将前面的路径 //信息全部剔除,以保证本地文件的安全。 if((ptr=strrchr(ncb.buff,':'))!=NULL)maxBlk=atoi(ptr+1); if(path)sprintf(fileName,"%s/%s",path,bfile); elsestrcpy(fileName,bfile); //与本地保存路径拼串,获得本地文件名称 fd=open(fileName,O_CREAT|O_WRONLY|O_TRUNC,0666); if(fd<0){ wLog(LOGERROR,"生成本地文件[%s]失败error[%d,%s]",fileName,errno,strerror(errno)); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-2; } //对需要保存的本地文件,使用清空方式,创建新文件,既是该文件已经存在 //也可以保证数据处理 wLog(LOGINFO,"创建本地文件[%s]成功",fileName); break; case200://保存文件内容 blknum++; maxBlk--; if(blknum==1||!maxBlk)wLog(LOGINFO,"接收数据[%s]成功",ncb.sndcmd+6); ncb.wlen=write(fd,ncb.buff+19,ncb.rlen-19); if(ncb.wlen!=ncb.rlen-19){ memcpy(ncb.sndcmd+23,"01",2); chkflg=-1; } elsefsize+=ncb.wlen; break; case300://文件传输结束 if(!maxBlk) wLog(LOGINFO,"文件[%s]成功接收,共[%d]传输块",fileName,blknum); else wLog(LOGERROR,"文件[%s]接收结束,差错[%d]传输块",fileName,maxBlk); close(fd); chkflg=1; break; } memcpy(ncb.sndcmd,"000019",6); ncb.sndcmd[22]='2'; ncb.wlen=tcp_writebuf(sfd,ncb.sndcmd,25,timeout); if(ncb.wlen!=25){ wLog(LOGERROR,"发送返回信息[%s]失败error[%d,%s]",ncb.sndcmd+6,errno,strerror(errno)); } if(chkflg)break; } if(fd)close(fd); wLog(LOGINFO,"成功接收[%s]文件,共[%ld]字节",fileName,fsize); returnchkflg; } //=============================客户端使用多文件发送程序===============================//// //// //socket方式文件发送程序,根据输入的netinfo建立通信通道,然后按照以下要求发送文件// //PUT100发送文件基本信息// //PUT200发送文件内容,根据要求循环执行,......// //PUT300数据发送结束// //// //=======================================================================================//// // //在建立好的文件传输通道上,将一个文件数据发送到服务端,传输后,不需要关闭传输通道。 // intcli_mput_sendFile(intsfd,char*localFile,char*remoteFile,intblockSize,inttimeout) { intfd; structstatsb; intiRet; intchkflg=0; intmaxBlk,blknum=0; char*ftr; longstart; longfsize; fd=-1; start=time(NULL); fd=open(localFile,O_RDONLY); if(fd==-1){ wLog(LOGERROR,"本地文件[%s]打开失败error[%d,%s]",localFile,errno,strerror(errno)); close(sfd); return-3; } if(fstat(fd,&sb)<0){ wLog(LOGERROR,"取[%s]基本信息失败error[%d,%s]",localFile,errno,strerror(errno)); chkflg=-3; gotomSend_END; } fsize=sb.st_size; if(blockSize>1024*MAXKB)blockSize=1024*MAXKB; if(blockSize<1024)blockSize=1024; wLog(LOGINFO,"成功打开本地文件[%s],size[%ld]",localFile,fsize); maxBlk=(int)((fsize)/blockSize); //计算本文件的最大传输次数 if(fsize%blockSize)maxBlk+=1; memset(&ncb,0x00,sizeof(structtcpBuffer)); ftr=strrchr(remoteFile,'/'); ncb.wlen=snprintf(ncb.buff+25,sizeof(ncb.buff)-1,"%s:%010ld:%010d:%010d", ftr?ftr+1:remoteFile,fsize,blockSize,maxBlk); sprintf(ncb.sndcmd,"%06d%-16s%1s%2s",ncb.wlen+19,"PUT100FILEINFO","1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.wlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen,timeout); if(iRet!=ncb.wlen){ wLog(LOGERROR,"发送[%d][%s]失败error[%d,%s]",ncb.wlen,remoteFile,errno,strerror(errno)); chkflg=-2; gotomSend_END; } wLog(LOGINFO,"发送报文头[%d][%s]成功",ncb.wlen,ncb.buff); ncb.rlen=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(ncb.rlen!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程保存[%s]失败error[%d,%s]",remoteFile,errno,strerror(errno)); chkflg=-2; gotomSend_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); while(1){ blknum++; memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=read(fd,ncb.buff+25,blockSize); if(ncb.rlen<1)break;//本地文件已经发送结束 sprintf(ncb.sndcmd,"%06dPUT200BLK%07d%1s%2s",ncb.rlen+19,blknum,"1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.rlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.rlen,timeout); if(iRet!=ncb.rlen){ wLog(LOGERROR,"发送[%s]失败error[%d,%s]",ncb.sndcmd,errno,strerror(errno)); chkflg=-1; gotomSend_END; } if(blknum==1||blknum==maxBlk) wLog(LOGINFO,"发送数据[%d][%s]成功",ncb.rlen,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收[%s]失败error[%d,%s]",ncb.rcvcmd,errno,strerror(errno)); chkflg=-1; gotomSend_END; } } memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.wlen=snprintf(ncb.sndcmd,sizeof(ncb.sndcmd)-1,"%-16s%1s%2s","PUT300FILEOVER","1","00"); sprintf(ncb.buff,"%06d%s",ncb.wlen,ncb.sndcmd); iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen+6,timeout); if(iRet!=ncb.wlen+6){ wLog(LOGERROR,"发送FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotomSend_END; } wLog(LOGINFO,"发送数据[%d][%s]成功",iRet,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotomSend_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); wLog(LOGINFO,"传输[%s]-->[%s][%d]块,共[%ld]字节,耗时%ld秒\n\n",localFile,remoteFile, blknum,fsize,time(NULL)-start); mSend_END: if(fd>0)close(fd); //关闭本文描述符和通信连接通道描述符 returnchkflg; } //=============================================多文件处理函数======================================// //// //// //多文件发送服务程序,本程序对使用":"分隔的文件信息自动进行分解,然后将每一个文件// //使用上述函数完成推送工作,在啊全部文件发送完毕后,程序将发出PUT500传输结束命令。// //// ///////////////////////////////////////////////////////////////////////////////////////////////////////// intcli_putm_sendFile(char*netinfo,char*sLocalFile,intblockSize,inttimeout) { intsfd; intiRet; intchkflg=0; structcli_putm_sendFile{ charlFile[NFILE+1];//本地文件名称 charrFile[NFILE+1];//远程文件名称 }mSnd; char*qlist,*ptr; char*ftr; intfnum=0; longstart; sfd=-1; start=time(NULL); sfd=make_tcpConnect(netinfo); //使用connect()建立到服务器的连接通道 if(sfd<0){ wLog(LOGERROR,"建立到[%s]文件传输通道失败error[%d,%s]",netinfo,errno,strerror(errno)); return-4; } wLog(LOGINFO,"成功建立到[%s]发送通道[%d]",netinfo,sfd); qlist=sLocalFile; ptr=strchr(qlist,':'); while(qlist!=NULL) { memset(&mSnd,0x00,sizeof(mSnd)); strncpy(mSnd.lFile,qlist,ptr-qlist); ftr=strrchr(mSnd.lFile,'/'); strcpy(mSnd.rFile,ftr?ftr+1:mSnd.lFile); iRet=cli_mput_sendFile(sfd,mSnd.lFile,mSnd.rFile,blockSize,timeout); if(iRet==0)fnum++; qlist=ptr+1; ptr=strchr(qlist,':'); } //对输入的文件名称进行分解,调用cli_mput_sendFile()函数进行数据发送。 memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.wlen=snprintf(ncb.sndcmd,sizeof(ncb.sndcmd)-1,"%-16s%1s%2s","PUT500FTPOVER","1","00"); sprintf(ncb.buff,"%06d%s",ncb.wlen,ncb.sndcmd); iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen+6,timeout); if(iRet!=ncb.wlen+6) { wLog(LOGERROR,"发送FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_put_sendFile_END; } wLog(LOGINFO,"发送数据[%d][%s]成功",iRet,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)) { wLog(LOGERROR,"远程接收FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_put_sendFile_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); wLog(LOGINFO,"共[%d]个文件,耗时%ld秒\n\n",fnum,time(NULL)-start); cli_put_sendFile_END: if(sfd>0)close(sfd); //关闭本文描述符和通信连接通道描述符 returnchkflg; } //============================服务端使用多文件传输程序===============================//// //// //socket文件接收服务程序,对收到的通信报文进行分析。// //在收到PUT100命令后,将该数据域中的文件名称与本地路径拼写得到完整的文件// //路径信息,打开本地文件。// //对PUT200数据域传输来的数据保存到本地文件中。// //收到PUT300命令,关闭当前传输文件。// //收到PUT500命令,TCP文件传输过程结束,退出程序。// //// //文件传输服务端程序:// //sfd在accept()后获取的新的客户端连接通道描述符// //path准备保存本地文件的路径信息// //fileName根据接收报文中的文件名称与本地路径拼串而得到的返回文件信息// //timeout数据传输需要使用的延时参数// //// //返回数据:// //0----文件接收成功// //-2--文件无法创建,打开文件名称失败// //-1--文件内容内容保存失败// //// //文件传输过程中,上传的文件名称有客户端提供,但是文件保存路径由服务器控制,以充分保证// //服务器文件系统的安全,避免服务器上的文件被客户端上传文件恶意覆盖。// //// //======================================================================================//// intsrv_mput_recvFile(intsfd,char*path,inttimeout) { intfd=-1; intblknum=0,maxBlk=0; charlocalFile[NFILE+1]; chartfile[NFILE+1],bfile[NFILE+1]; char*ptr; longfsize=0; longstart=time(NULL); intchkflg=0; intfnum=0; memset(tfile,0x00,sizeof(tfile)); while(1){ memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=tcp_readbuf(6,sfd,ncb.buff,sizeof(ncb.buff)-1,timeout); if(ncb.rlen<0)break; memcpy(ncb.sndcmd+6,ncb.buff,19); if(memcmp(ncb.buff,"PUT",3)){ wLog(LOGERROR,"接收命令序列[%s]错误,程序退出.",ncb.sndcmd+6); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-3; } switch(Nstr_int(ncb.buff+3,3)){ //获取PUT后面的命令控制字,下面分析该控制字进行工作 case100://开始接收文件,打开本地文件 blknum=maxBlk=0; wLog(LOGINFO,"接收管理报文[%s]成功",ncb.buff); //对于接收到的第一条命令,打印该控制命令的全部内容 ptr=strchr(ncb.buff,':'); if(ptr)memcpy(tfile,ncb.buff+19,ptr-(char*)ncb.buff-19); elsestrcpy(tfile,ncb.buff+19); //获取传输来的文件名称 ptr=strrchr(tfile,'/'); if(ptr)strcpy(bfile,ptr+1); elsestrcpy(bfile,tfile); //检查传输来文件名称中的路径信息,得到基本文件名称,将前面的路径 //信息全部剔除,以保证本地文件的安全。当传输文件名称带有".."标志 //的时候,将会对服务器文件系统产生影响,需要保证该问题不会出现。 if((ptr=strrchr(ncb.buff,':'))!=NULL)maxBlk=atoi(ptr+1); //从命令报文中得到文件传输块信息。 if(path)sprintf(localFile,"%s/%s",path,bfile); elsestrcpy(localFile,bfile); //与本地保存路径拼串,获得本地文件名称 fd=open(localFile,O_CREAT|O_WRONLY|O_TRUNC,0666); if(fd<0){ wLog(LOGERROR,"生成本地文件[%s]失败error[%d,%s]",localFile,errno,strerror(errno)); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-2; } fnum++; //对需要保存的本地文件,使用清空方式,创建新文件,既是该文件已经存在 //也可以保证数据处理 wLog(LOGINFO,"创建本地文件[%s]成功",localFile); break; case200://保存文件内容 blknum++; maxBlk--; if(blknum==1||!maxBlk)wLog(LOGINFO,"接收数据[%s]成功",ncb.sndcmd+6); ncb.wlen=write(fd,ncb.buff+19,ncb.rlen-19); if(ncb.wlen!=ncb.rlen-19){ memcpy(ncb.sndcmd+23,"01",2); chkflg=-1; } elsefsize+=ncb.wlen; break; case300://文件传输结束 if(!maxBlk) wLog(LOGINFO,"文件[%s]成功接收,共[%d]传输块",localFile,blknum); else wLog(LOGERROR,"文件[%s]接收结束,差错[%d]传输块",localFile,maxBlk); close(fd); break; case500://通信处理结束 chkflg=1; break; } memcpy(ncb.sndcmd,"000019",6); ncb.sndcmd[22]='2'; ncb.wlen=tcp_writebuf(sfd,ncb.sndcmd,25,timeout); if(ncb.wlen!=25){ wLog(LOGERROR,"发送返回信息[%s]失败error[%d,%s]",ncb.sndcmd+6,errno,strerror(errno)); } if(chkflg)break; } if(fd)close(fd); wLog(LOGINFO,"成功接收[%d]文件,耗时[%ld]秒",fnum,time(NULL)-start); returnchkflg; } //==================================================================================================// ///////////////////////////////////以下为客户端主动下载类程序/////////////////////////////////////////// //=============================客户端使用文件发送程序=================================//// //// //socket方式文件发送程序,根据输入的netinfo建立通信通道,然后按照以下要求发送文件// //GET100发送文件下载请求,将远程文件名称和分块尺寸上送主机,等主机回应// //GET200接收文件内容,根据要求循环执行,......// //GET300数据发送结束// //// //=======================================================================================//// intcli_get_sendFile(char*netinfo,char*localFile,char*remoteFile,intblockSize,inttimeout) { intsfd,fd; structstatsb; intiRet; intchkflg=0; intmaxBlk,blknum=0; longstart; longfsize; sfd=fd=-1; start=time(NULL); sfd=make_tcpConnect(netinfo); //申请socket描述符,使用connect()建立到服务器的连接通道 if(sfd<0){ wLog(LOGERROR,"建立到[%s]连接失败error[%d,%s]",netinfo,errno,strerror(errno)); return-4; } wLog(LOGINFO,"成功建立到[%s]发送通道[%d]",netinfo,sfd); fd=open(localFile,O_CREAT|O_WRONLY|O_TRUNC,0666); if(fd==-1){ wLog(LOGERROR,"本地文件[%s]打开失败error[%d,%s]",localFile,errno,strerror(errno)); close(sfd); return-3; } if(fstat(fd,&sb)<0){ wLog(LOGERROR,"取[%s]文件信息失败error[%d,%s]",localFile,errno,strerror(errno)); chkflg=-3; gotocli_get_sendFile_END; } fsize=sb.st_size; if(blockSize>1024*MAXKB)blockSize=1024*MAXKB; if(blockSize<1024)blockSize=1024; wLog(LOGINFO,"成功打开本地文件[%s],size[%ld]",localFile,fsize); maxBlk=(int)((fsize)/blockSize); //计算本文件的最大传输次数 if(fsize%blockSize)maxBlk+=1; //不足整块的数据,需要按一块进行处理。 memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.wlen=snprintf(ncb.buff+25,sizeof(ncb.buff)-1,"%s:%010ld:%010d:%010d", remoteFile,0L,blockSize,0); sprintf(ncb.sndcmd,"%06d%-16s%1s%2s",ncb.wlen+19,"GET100FILEINFO","1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.wlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen,timeout); if(iRet!=ncb.wlen){ wLog(LOGERROR,"发送[%d][%s]失败error[%d,%s]",ncb.wlen,remoteFile,errno,strerror(errno)); chkflg=-2; gotocli_get_sendFile_END; } wLog(LOGINFO,"发送报文头[%d][%s]成功",ncb.wlen,ncb.buff); ncb.rlen=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(ncb.rlen!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程保存[%s]失败error[%d,%s]",remoteFile,errno,strerror(errno)); chkflg=-2; gotocli_get_sendFile_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); while(1){ blknum++; memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=read(fd,ncb.buff+25,blockSize); if(ncb.rlen<1)break;//本地文件已经发送结束 sprintf(ncb.sndcmd,"%06dGET200BLK%07d%1s%2s",ncb.rlen+19,blknum,"1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.rlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.rlen,timeout); if(iRet!=ncb.rlen){ wLog(LOGERROR,"发送[%s]失败error[%d,%s]",ncb.sndcmd,errno,strerror(errno)); chkflg=-1; gotocli_get_sendFile_END; } if(blknum==1||blknum==maxBlk) wLog(LOGINFO,"发送数据[%d][%s]成功",ncb.rlen,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收[%s]失败error[%d,%s]",ncb.rcvcmd,errno,strerror(errno)); chkflg=-1; gotocli_get_sendFile_END; } } memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.wlen=snprintf(ncb.sndcmd,sizeof(ncb.sndcmd)-1,"%-16s%1s%2s","GET300FILEOVER","1","00"); sprintf(ncb.buff,"%06d%s",ncb.wlen,ncb.sndcmd); iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen+6,timeout); if(iRet!=ncb.wlen+6){ wLog(LOGERROR,"发送FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_get_sendFile_END; } wLog(LOGINFO,"发送数据[%d][%s]成功",iRet,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_get_sendFile_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); wLog(LOGINFO,"传输[%s]-->[%s][%d]块,共[%ld]字节,耗时%ld秒\n\n",localFile,remoteFile, blknum,fsize,time(NULL)-start); cli_get_sendFile_END: if(sfd>0)close(sfd); if(fd>0)close(fd); //关闭本文描述符和通信连接通道描述符 returnchkflg; } //============================服务端使用文件传输程序=================================//// //// //socket文件接收服务程序,对收到的通信报文进行分析。// //在收到GET100命令后,将该数据域中的文件名称与本地路径拼写得到完整的文件// //路径信息,打开本地文件。// //对GET200数据域传输来的数据保存到本地文件中。// //收到GET300命令,关闭本地文件,传输过程结束。// //// //文件传输服务端程序:// //sfd在accept()后获取的新的客户端连接通道描述符// //path准备保存本地文件的路径信息// //fileName根据接收报文中的文件名称与本地路径拼串而得到的返回文件信息// //timeout数据传输需要使用的延时参数// //// //返回数据:// //0----文件接收成功// //-2--文件无法创建,打开文件名称失败// //-1--文件内容内容保存失败// //======================================================================================//// intsrv_get_recvFile(intsfd,char*path,char*fileName,inttimeout) { intfd=-1; intblknum=0,maxBlk=0; chartfile[NFILE+1],bfile[NFILE+1]; char*ptr; longfsize=0; intchkflg=0; memset(tfile,0x00,sizeof(tfile)); while(1){ memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=tcp_readbuf(6,sfd,ncb.buff,sizeof(ncb.buff)-1,timeout); if(ncb.rlen<0)break; memcpy(ncb.sndcmd+6,ncb.buff,19); if(memcmp(ncb.buff,"GET",3)){ wLog(LOGERROR,"接收命令序列[%s]错误,程序退出.",ncb.sndcmd+6); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-3; } switch(Nstr_int(ncb.buff+3,3)){ //获取get后面的命令控制字,下面分析该控制字进行工作 case100://开始接收文件,打开本地文件 wLog(LOGINFO,"接收管理报文[%s]成功",ncb.buff); //对于接收到的第一条命令,打印该控制命令的全部内容 ptr=strchr(ncb.buff,':'); if(ptr)memcpy(tfile,ncb.buff+19,ptr-(char*)ncb.buff-19); elsestrcpy(tfile,ncb.buff+19); //获取传输来的文件名称 ptr=strrchr(tfile,'/'); if(ptr)strcpy(bfile,ptr+1); elsestrcpy(bfile,tfile); //检查传输来文件名称中的路径信息,得到基本文件名称,将前面的路径 //信息全部剔除,以保证本地文件的安全。 if((ptr=strrchr(ncb.buff,':'))!=NULL)maxBlk=atoi(ptr+1); if(path)sprintf(fileName,"%s/%s",path,bfile); elsestrcpy(fileName,bfile); //与本地保存路径拼串,获得本地文件名称 fd=open(fileName,O_CREAT|O_WRONLY|O_TRUNC,0666); if(fd<0){ wLog(LOGERROR,"生成本地文件[%s]失败error[%d,%s]",fileName,errno,strerror(errno)); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-2; } //对需要保存的本地文件,使用清空方式,创建新文件,既是该文件已经存在 //也可以保证数据处理 wLog(LOGINFO,"创建本地文件[%s]成功",fileName); break; case200://保存文件内容 blknum++; maxBlk--; if(blknum==1||!maxBlk)wLog(LOGINFO,"接收数据[%s]成功",ncb.sndcmd+6); ncb.wlen=write(fd,ncb.buff+19,ncb.rlen-19); if(ncb.wlen!=ncb.rlen-19){ memcpy(ncb.sndcmd+23,"01",2); chkflg=-1; } elsefsize+=ncb.wlen; break; case300://文件传输结束 if(!maxBlk) wLog(LOGINFO,"文件[%s]成功接收,共[%d]传输块",fileName,blknum); else wLog(LOGERROR,"文件[%s]接收结束,差错[%d]传输块",fileName,maxBlk); close(fd); chkflg=1; break; } memcpy(ncb.sndcmd,"000019",6); ncb.sndcmd[22]='2'; ncb.wlen=tcp_writebuf(sfd,ncb.sndcmd,25,timeout); if(ncb.wlen!=25){ wLog(LOGERROR,"发送返回信息[%s]失败error[%d,%s]",ncb.sndcmd+6,errno,strerror(errno)); } if(chkflg)break; } if(fd)close(fd); wLog(LOGINFO,"成功接收[%s]文件,共[%ld]字节",fileName,fsize); returnchkflg; } //=============================客户端使用多文件发送程序===============================//// //// //socket方式文件发送程序,根据输入的netinfo建立通信通道,然后按照以下要求发送文件// //GET100发送文件基本信息// //GET200发送文件内容,根据要求循环执行,......// //GET300数据发送结束// //// //=======================================================================================//// // //在建立好的文件传输通道上,将一个文件数据发送到服务端,传输后,不需要关闭传输通道。 // intcli_mget_sendFile(intsfd,char*localFile,char*remoteFile,intblockSize,inttimeout) { intfd=-1; structstatsb; intiRet; intchkflg=0; intmaxBlk,blknum=0; char*ftr; longstart; longfsize; start=time(NULL); fd=open(localFile,O_RDONLY); if(fd==-1){ wLog(LOGERROR,"本地文件[%s]打开失败error[%d,%s]",localFile,errno,strerror(errno)); close(sfd); return-3; } if(fstat(fd,&sb)<0){ wLog(LOGERROR,"取[%s]基本信息失败error[%d,%s]",localFile,errno,strerror(errno)); chkflg=-3; gotomSend_END; } fsize=sb.st_size; if(blockSize>1024*MAXKB)blockSize=1024*MAXKB; if(blockSize<1024)blockSize=1024; wLog(LOGINFO,"成功打开本地文件[%s],size[%ld]",localFile,fsize); maxBlk=(int)((fsize)/blockSize); //计算本文件的最大传输次数 if(fsize%blockSize)maxBlk+=1; memset(&ncb,0x00,sizeof(structtcpBuffer)); ftr=strrchr(remoteFile,'/'); ncb.wlen=snprintf(ncb.buff+25,sizeof(ncb.buff)-1,"%s:%010ld:%010d:%010d", ftr?ftr+1:remoteFile,fsize,blockSize,maxBlk); sprintf(ncb.sndcmd,"%06d%-16s%1s%2s",ncb.wlen+19,"GET100FILEINFO","1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.wlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen,timeout); if(iRet!=ncb.wlen){ wLog(LOGERROR,"发送[%d][%s]失败error[%d,%s]",ncb.wlen,remoteFile,errno,strerror(errno)); chkflg=-2; gotomSend_END; } wLog(LOGINFO,"发送报文头[%d][%s]成功",ncb.wlen,ncb.buff); ncb.rlen=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(ncb.rlen!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程保存[%s]失败error[%d,%s]",remoteFile,errno,strerror(errno)); chkflg=-2; gotomSend_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); while(1) { blknum++; memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=read(fd,ncb.buff+25,blockSize); if(ncb.rlen<1)break;//本地文件已经发送结束 sprintf(ncb.sndcmd,"%06dGET200BLK%07d%1s%2s",ncb.rlen+19,blknum,"1","00"); memcpy(ncb.buff,ncb.sndcmd,25); ncb.rlen+=25; iRet=tcp_writebuf(sfd,ncb.buff,ncb.rlen,timeout); if(iRet!=ncb.rlen){ wLog(LOGERROR,"发送[%s]失败error[%d,%s]",ncb.sndcmd,errno,strerror(errno)); chkflg=-1; gotomSend_END; } if(blknum==1||blknum==maxBlk) wLog(LOGINFO,"发送数据[%d][%s]成功",ncb.rlen,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收[%s]失败error[%d,%s]",ncb.rcvcmd,errno,strerror(errno)); chkflg=-1; gotomSend_END; } } memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.wlen=snprintf(ncb.sndcmd,sizeof(ncb.sndcmd)-1,"%-16s%1s%2s","GET300FILEOVER","1","00"); sprintf(ncb.buff,"%06d%s",ncb.wlen,ncb.sndcmd); iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen+6,timeout); if(iRet!=ncb.wlen+6){ wLog(LOGERROR,"发送FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotomSend_END; } wLog(LOGINFO,"发送数据[%d][%s]成功",iRet,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotomSend_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); wLog(LOGINFO,"传输[%s]-->[%s][%d]块,共[%ld]字节,耗时%ld秒\n\n",localFile,remoteFile, blknum,fsize,time(NULL)-start); mSend_END: if(fd>0)close(fd); //关闭本文描述符和通信连接通道描述符 returnchkflg; } //=============================================多文件处理函数======================================// //// //// //多文件发送服务程序,本程序对使用":"分隔的文件信息自动进行分解,然后将每一个文件// //使用上述函数完成推送工作,在啊全部文件发送完毕后,程序将发出get500传输结束命令。// //// ///////////////////////////////////////////////////////////////////////////////////////////////////////// intcli_getm_sendFile(char*netinfo,char*sLocalFile,intblockSize,inttimeout) { intsfd=-1; intiRet; intchkflg=0; structcli_getm_sendFile{ charlFile[NFILE+1];//本地文件名称 charrFile[NFILE+1];//远程文件名称 }mSnd; char*qlist,*ptr; char*ftr; intfnum=0; longstart; start=time(NULL); sfd=make_tcpConnect(netinfo); //使用connect()建立到服务器的连接通道 if(sfd<0){ wLog(LOGERROR,"建立到[%s]文件传输通道失败error[%d,%s]",netinfo,errno,strerror(errno)); return-4; } wLog(LOGINFO,"成功建立到[%s]发送通道[%d]",netinfo,sfd); qlist=sLocalFile; ptr=strchr(qlist,':'); while(qlist!=NULL){ memset(&mSnd,0x00,sizeof(mSnd)); strncpy(mSnd.lFile,qlist,ptr-qlist); ftr=strrchr(mSnd.lFile,'/'); strcpy(mSnd.rFile,ftr?ftr+1:mSnd.lFile); iRet=cli_mget_sendFile(sfd,mSnd.lFile,mSnd.rFile,blockSize,timeout); if(iRet==0)fnum++; qlist=ptr+1; ptr=strchr(qlist,':'); } //对输入的文件名称进行分解,调用cli_mget_sendFile()函数进行数据发送。 memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.wlen=snprintf(ncb.sndcmd,sizeof(ncb.sndcmd)-1,"%-16s%1s%2s","get500FTPOVER","1","00"); sprintf(ncb.buff,"%06d%s",ncb.wlen,ncb.sndcmd); iRet=tcp_writebuf(sfd,ncb.buff,ncb.wlen+6,timeout); if(iRet!=ncb.wlen+6){ wLog(LOGERROR,"发送FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_get_sendFile_END; } wLog(LOGINFO,"发送数据[%d][%s]成功",iRet,ncb.sndcmd); iRet=tcp_readbuf(6,sfd,ncb.rcvcmd,19,timeout); if(iRet!=19||memcmp(ncb.rcvcmd+17,"00",2)){ wLog(LOGERROR,"远程接收FileOver失败error[%d,%s]",errno,strerror(errno)); chkflg=-1; gotocli_get_sendFile_END; } wLog(LOGINFO,"接到返回数据[%s]成功",ncb.rcvcmd); wLog(LOGINFO,"共[%d]个文件,耗时%ld秒\n\n",fnum,time(NULL)-start); cli_get_sendFile_END: if(sfd>0)close(sfd); //关闭本文描述符和通信连接通道描述符 returnchkflg; } //============================服务端使用多文件传输程序===============================//// //// //socket文件接收服务程序,对收到的通信报文进行分析。// //在收到GET100命令后,将该数据域中的文件名称与本地路径拼写得到完整的文件// //路径信息,打开本地文件。// //对GET200数据域传输来的数据保存到本地文件中。// //收到GET300命令,关闭当前传输文件。// //收到get500命令,TCP文件传输过程结束,退出程序。// //// //文件传输服务端程序:// //sfd在accept()后获取的新的客户端连接通道描述符// //path准备保存本地文件的路径信息// //fileName根据接收报文中的文件名称与本地路径拼串而得到的返回文件信息// //timeout数据传输需要使用的延时参数// //// //返回数据:// //0----文件接收成功// //-2--文件无法创建,打开文件名称失败// //-1--文件内容内容保存失败// //// //文件传输过程中,上传的文件名称有客户端提供,但是文件保存路径由服务器控制,以充分保证// //服务器文件系统的安全,避免服务器上的文件被客户端上传文件恶意覆盖。// //// //======================================================================================//// intsrv_mget_recvFile(intsfd,char*path,inttimeout) { intfd=-1; intblknum=0,maxBlk=0; charlocalFile[NFILE+1]; chartfile[NFILE+1],bfile[NFILE+1]; char*ptr; longfsize=0; longstart=time(NULL); intchkflg=0; intfnum=0; memset(tfile,0x00,sizeof(tfile)); while(1){ memset(&ncb,0x00,sizeof(structtcpBuffer)); ncb.rlen=tcp_readbuf(6,sfd,ncb.buff,sizeof(ncb.buff)-1,timeout); if(ncb.rlen<0)break; memcpy(ncb.sndcmd+6,ncb.buff,19); if(memcmp(ncb.buff,"get",3)!=0){ wLog(LOGERROR,"接收命令序列[%s]错误,程序退出.",ncb.sndcmd+6); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-3; } switch(Nstr_int(ncb.buff+3,3)) { //获取get后面的命令控制字,下面分析该控制字进行工作 case100://开始接收文件,打开本地文件 blknum=maxBlk=0; wLog(LOGINFO,"接收管理报文[%s]成功",ncb.buff); //对于接收到的第一条命令,打印该控制命令的全部内容 ptr=strchr(ncb.buff,':'); if(ptr)memcpy(tfile,ncb.buff+19,ptr-(char*)ncb.buff-19); elsestrcpy(tfile,ncb.buff+19); //获取传输来的文件名称 ptr=strrchr(tfile,'/'); if(ptr)strcpy(bfile,ptr+1); elsestrcpy(bfile,tfile); //检查传输来文件名称中的路径信息,得到基本文件名称,将前面的路径 //信息全部剔除,以保证本地文件的安全。当传输文件名称带有".."标志 //的时候,将会对服务器文件系统产生影响,需要保证该问题不会出现。 if((ptr=strrchr(ncb.buff,':'))!=NULL)maxBlk=atoi(ptr+1); //从命令报文中得到文件传输块信息。 if(path)sprintf(localFile,"%s/%s",path,bfile); elsestrcpy(localFile,bfile); //与本地保存路径拼串,获得本地文件名称 fd=open(localFile,O_CREAT|O_WRONLY|O_TRUNC,0666); if(fd<0){ wLog(LOGERROR,"生成本地文件[%s]失败error[%d,%s]",localFile,errno,strerror(errno)); memcpy(ncb.rcvcmd+23,"01",2); chkflg=-2; } fnum++; //对需要保存的本地文件,使用清空方式,创建新文件,既是该文件已经存在 //也可以保证数据处理 wLog(LOGINFO,"创建本地文件[%s]成功",localFile); break; case200://保存文件内容 blknum++; maxBlk--; if(blknum==1||!maxBlk)wLog(LOGINFO,"接收数据[%s]成功",ncb.sndcmd+6); ncb.wlen=write(fd,ncb.buff+19,ncb.rlen-19); if(ncb.wlen!=ncb.rlen-19){ memcpy(ncb.sndcmd+23,"01",2); chkflg=-1; } elsefsize+=ncb.wlen; break; case300://文件传输结束 if(!maxBlk) wLog(LOGINFO,"文件[%s]成功接收,共[%d]传输块",localFile,blknum); else wLog(LOGERROR,"文件[%s]接收结束,差错[%d]传输块",localFile,maxBlk); close(fd); break; case500://通信处理结束 chkflg=1; break; } memcpy(ncb.sndcmd,"000019",6); ncb.sndcmd[22]='2'; ncb.wlen=tcp_writebuf(sfd,ncb.sndcmd,25,timeout); if(ncb.wlen!=25){ wLog(LOGERROR,"发送返回信息[%s]失败error[%d,%s]",ncb.sndcmd+6,errno,strerror(errno)); } if(chkflg)break; } if(fd)close(fd); wLog(LOGINFO,"成功接收[%d]文件,耗时[%ld]秒",fnum,time(NULL)-start); returnchkflg; } #endif
以上就是本文的全部内容,希望对大家的学习有所帮助。