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
以上就是本文的全部内容,希望对大家的学习有所帮助。