亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++文件上傳、下載工具

2020-01-26 14:36:06
字體:
來源:轉載
供稿:網友

本文實例為大家分享了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" #define  CMDHEAD  6  // 通信報文頭信息長度#define  CMDINFO  6  // 空值命令 PUT GET#define  CMD #define  MAXKB   16#define  NCMD   32#define  NFILE   128 // tcp 通信命令行緩沖區typedef struct tcpCmd {  int  len;      // 命令行長度  char cmd[NCMD+1];  // 命令行緩沖區} tcpCmd; struct tcpBuffer {   int rlen;      // 接收數據長度  int wlen;      // 發送數據長度   char rcvcmd[NCMD+1];  // 接收命令域數據  char sndcmd[NCMD+1];  // 接收命令域數據   tcpCmd rCmd    ;  // 接收緩沖區  tcpCmd sCmd    ;  // 發送緩沖區   char buff[1024 * MAXKB + 64 + 1 ];  // 報文緩沖區, 包含命令控制串和實際報文數據 } ncb;   // ////////////////////////////////////////////////////////////////////////////////////////////// //////                                                //// 根據報文頭數據要求,接收一個通信數據。                            //// 程序首先按照要求讀取 headlen 長度的長度包數據,然后再次從網絡上讀取真正長度的數據包。     ////                                                //// 數據接收函數分兩次進行處理,返回數據 sData 中已經不再包含 6位通信長度數據。          //// ///////////////////////////////////////////////////////////////////////////////////////////// ////int tcp_readbuf(int headlen, int sfd, char * sData, int MaxLen, int sTime){  int iRet = 0;  int left_bytes, thisRead, sLen;  char *ptr = sData;   struct timeval tv;  fd_set rfds;  char  temp[ 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_readbuf select 延時[%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);  else sLen = 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字節//int tcp_writebuf(int sfd, char * sData, int sLen, int sTime){  int iRet = 0;  int left_bytes, thisWrite;  char *ptr = sData;  fd_set wfds;  struct timeval tv;    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_writebuf select 延時[%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_sendbuf left_bytes[%d] faile [%d, %s]", left_bytes, errno, strerror(errno) );  return(sLen-left_bytes);} //  ============================= 客戶端使用 文件發送程序 ================================= //////                                              ////  socket 方式文件發送程序,根據輸入的 netinfo 建立通信通道,然后按照以下要求發送文件   ////  PUT100 發送文件基本信息                                 ////  PUT200 發送文件內容,根據要求循環執行,......                      ////  PUT300 數據發送結束                                   ////                                              ////  ======================================================================================= //// int  cli_put_sendFile(char *netinfo, char *localFile, char *remoteFile, int blockSize, int timeout){  int sfd, fd;   struct stat sb;  int  iRet ;  int  chkflg = 0 ;  int  maxBlk, blknum = 0;   long  start;   long fsize;   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;    goto cli_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 (struct tcpBuffer));   // 準備發送文件控制命令串, 告訴對方準備發送文件的基礎信息  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;    goto cli_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;    goto cli_put_sendFile_END;  }  wLog(LOGINFO,"接到返回數據 [%s]成功", ncb.rcvcmd );    // 循環將本地文件全部發送完畢  while ( 1 ){    blknum ++;    memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));    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;      goto cli_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;      goto cli_put_sendFile_END;    }  }   memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));   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;    goto cli_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;    goto cli_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);  // 關閉本文描述符和通信連接通道描述符   return chkflg;}  //  ============================ 服務端使用 文件傳輸程序 ================================= //////                                             ////  socket 文件接收服務程序,對收到的通信報文進行分析。                  ////  在收到 PUT100 命令后,將該數據域中的文件名稱與本地路徑拼寫得到完整的文件        ////         路徑信息,打開本地文件。                         ////  對 PUT200 數據域傳輸來的數據保存到本地文件中。                     ////  收到 PUT300 命令,關閉本地文件,傳輸過程結束。                     ////                                             ////  文件傳輸服務端程序:                                  ////  sfd  在 accept() 后獲取的新的客戶端連接通道描述符                   ////  path 準備保存本地文件的路徑信息                            ////  fileName 根據接收報文中的文件名稱與本地路徑拼串而得到的返回文件信息          ////  timeout  數據傳輸需要使用的延時參數                          ////                                             ////  返回數據:                                       ////  0 ---- 文件接收成功                                  ////  -2 -- 文件無法創建,打開文件名稱失敗                          ////  -1 -- 文件內容內容保存失敗                               ////  ====================================================================================== ////int srv_put_recvFile(int sfd , char *path, char *fileName, int timeout ){  int  fd = -1;   int  blknum = 0, maxBlk=0 ;  char  tfile[NFILE+1], bfile[NFILE+1];  char  *ptr;   long  fsize = 0;   int  chkflg = 0;    memset(tfile, 0x00, sizeof(tfile));   while ( 1 ){    memset(&ncb, 0x00, sizeof (struct tcpBuffer));     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 后面的命令控制字,下面分析該控制字進行工作      case 100 : // 開始接收文件,打開本地文件        wLog(LOGINFO, "接收管理報文[%s]成功", ncb.buff );        // 對于接收到的第一條命令,打印該控制命令的全部內容         ptr = strchr(ncb.buff, ':');        if(ptr) memcpy(tfile, ncb.buff+19, ptr - (char *)ncb.buff - 19);        else  strcpy(tfile, ncb.buff+19);        // 獲取傳輸來的文件名稱         ptr = strrchr(tfile, '/');        if(ptr) strcpy(bfile, ptr+1);        else  strcpy(bfile, tfile);        // 檢查傳輸來文件名稱中的路徑信息,得到基本文件名稱,將前面的路徑        // 信息全部剔除,以保證本地文件的安全。         if( (ptr = strrchr(ncb.buff , ':') ) != NULL ) maxBlk = atoi (ptr +1);         if( path ) sprintf(fileName, "%s/%s", path, bfile);        else    strcpy(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 ;      case 200 :  // 保存文件內容        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;        }        else fsize += ncb.wlen ;        break ;      case 300 : // 文件傳輸結束        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 );   return chkflg ;}  //  ============================= 客戶端使用 多文件發送程序 =============================== //////                                              ////  socket 方式文件發送程序,根據輸入的 netinfo 建立通信通道,然后按照以下要求發送文件   ////  PUT100 發送文件基本信息                                 ////  PUT200 發送文件內容,根據要求循環執行,......                      ////  PUT300 數據發送結束                                   ////                                              ////  ======================================================================================= //// //// 在建立好的文件傳輸通道上,將一個文件數據發送到服務端,傳輸后,不需要關閉傳輸通道。//int  cli_mput_sendFile(int sfd, char *localFile, char *remoteFile, int blockSize, int timeout ){  int  fd;   struct stat sb;  int  iRet ;  int  chkflg = 0 ;  int  maxBlk, blknum = 0;  char  *ftr;   long  start;   long  fsize;   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;    goto mSend_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 (struct tcpBuffer));   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;    goto mSend_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;    goto mSend_END;  }  wLog(LOGINFO,"接到返回數據 [%s]成功", ncb.rcvcmd );    while ( 1 ){    blknum ++;    memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));    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;      goto mSend_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;      goto mSend_END;    }  }   memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));   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;    goto mSend_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;    goto mSend_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);  // 關閉本文描述符和通信連接通道描述符   return chkflg; } // ============================================= 多文件處理函數 ====================================== ////                                                   ////                                                   //// 多文件發送服務程序,本程序對使用 ":" 分隔的文件信息自動進行分解,然后將每一個文件          //// 使用上述函數完成推送工作,在啊全部文件發送完畢后,程序將發出 PUT500 傳輸結束命令。         ////                                                   ///////////////////////////////////////////////////////////////////////////////////////////////////////////int  cli_putm_sendFile(char *netinfo, char *sLocalFile, int blockSize, int timeout){  int sfd;   int  iRet ;  int  chkflg = 0 ;   struct cli_putm_sendFile{    char lFile[NFILE+1];   // 本地文件名稱    char rFile[NFILE+1];   // 遠程文件名稱  }mSnd;   char  *qlist , *ptr ;  char  *ftr;  int  fnum = 0;  long  start ;     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 (struct tcpBuffer ));   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;    goto cli_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;    goto cli_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);  // 關閉本文描述符和通信連接通道描述符   return chkflg;}  //  ============================ 服務端使用 多文件傳輸程序 =============================== //////                                             ////  socket 文件接收服務程序,對收到的通信報文進行分析。                  ////  在收到 PUT100 命令后,將該數據域中的文件名稱與本地路徑拼寫得到完整的文件        ////         路徑信息,打開本地文件。                         ////  對 PUT200 數據域傳輸來的數據保存到本地文件中。                     ////  收到 PUT300 命令,關閉當前傳輸文件。                          ////  收到 PUT500 命令,TCP 文件傳輸過程結束,退出程序。                   ////                                             ////  文件傳輸服務端程序:                                  ////  sfd  在 accept() 后獲取的新的客戶端連接通道描述符                   ////  path 準備保存本地文件的路徑信息                            ////  fileName 根據接收報文中的文件名稱與本地路徑拼串而得到的返回文件信息          ////  timeout  數據傳輸需要使用的延時參數                          ////                                             ////  返回數據:                                       ////  0 ---- 文件接收成功                                  ////  -2 -- 文件無法創建,打開文件名稱失敗                          ////  -1 -- 文件內容內容保存失敗                               ////                                             ////  文件傳輸過程中,上傳的文件名稱有客戶端提供,但是文件保存路徑由服務器控制,以充分保證  ////  服務器文件系統的安全,避免服務器上的文件被客戶端上傳文件惡意覆蓋。           ////                                             ////  ====================================================================================== ////int srv_mput_recvFile(int sfd , char *path, int timeout ){  int fd = -1;   int  blknum = 0 , maxBlk = 0 ;  char  localFile[NFILE+1];  char  tfile[NFILE+1], bfile[NFILE+1];  char  *ptr;   long  fsize = 0;  long  start = time(NULL);   int  chkflg = 0;  int  fnum = 0;    memset(tfile, 0x00, sizeof(tfile));   while (1){    memset(&ncb, 0x00, sizeof (struct tcpBuffer));     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 后面的命令控制字,下面分析該控制字進行工作      case 100 : // 開始接收文件,打開本地文件        blknum = maxBlk = 0 ;        wLog(LOGINFO, "接收管理報文[%s]成功", ncb.buff );        // 對于接收到的第一條命令,打印該控制命令的全部內容         ptr = strchr(ncb.buff, ':');        if(ptr) memcpy(tfile, ncb.buff+19, ptr - (char *)ncb.buff - 19);        else  strcpy(tfile, ncb.buff+19);        // 獲取傳輸來的文件名稱         ptr = strrchr(tfile, '/');        if(ptr) strcpy(bfile, ptr+1);        else  strcpy(bfile, tfile);        // 檢查傳輸來文件名稱中的路徑信息,得到基本文件名稱,將前面的路徑        // 信息全部剔除,以保證本地文件的安全。當傳輸文件名稱帶有 ".." 標志        // 的時候,將會對服務器文件系統產生影響,需要保證該問題不會出現。         if( (ptr = strrchr(ncb.buff , ':') ) != NULL ) maxBlk = atoi (ptr +1);        // 從命令報文中得到文件傳輸塊信息。         if( path ) sprintf(localFile, "%s/%s", path, bfile);        else    strcpy(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 ;      case 200 :  // 保存文件內容        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;        }        else fsize += ncb.wlen ;         break ;      case 300 : // 文件傳輸結束        if( !maxBlk )          wLog(LOGINFO, " 文件[%s]成功接收,共 [%d] 傳輸塊 ", localFile, blknum );        else          wLog(LOGERROR,"文件[%s]接收結束,差錯 [%d] 傳輸塊 ", localFile , maxBlk );         close(fd);        break ;      case 500 : // 通信處理結束        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 );   return chkflg ;}  // ================================================================================================== /////////////////////////////////////以下為客戶端主動下載類程序/////////////////////////////////////////////  ============================= 客戶端使用 文件發送程序 ================================= //////                                              ////  socket 方式文件發送程序,根據輸入的 netinfo 建立通信通道,然后按照以下要求發送文件   ////  GET100 發送文件下載請求,將遠程文件名稱和分塊尺寸上送主機,等主機回應          ////  GET200 接收文件內容,根據要求循環執行,......                      ////  GET300 數據發送結束                                   ////                                              ////  ======================================================================================= //// int  cli_get_sendFile(char *netinfo, char *localFile, char *remoteFile, int blockSize, int timeout){  int sfd, fd;   struct stat sb;  int  iRet ;  int  chkflg = 0 ;  int  maxBlk, blknum = 0;   long  start;   long fsize;   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;    goto cli_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 (struct tcpBuffer));   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;    goto cli_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;    goto cli_get_sendFile_END;  }  wLog(LOGINFO,"接到返回數據 [%s]成功", ncb.rcvcmd );    while (1){    blknum ++;    memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));    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;      goto cli_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;      goto cli_get_sendFile_END;    }  }   memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));   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;    goto cli_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;    goto cli_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);  // 關閉本文描述符和通信連接通道描述符   return chkflg;}  //  ============================ 服務端使用 文件傳輸程序 ================================= //////                                             ////  socket 文件接收服務程序,對收到的通信報文進行分析。                  ////  在收到 GET100 命令后,將該數據域中的文件名稱與本地路徑拼寫得到完整的文件        ////         路徑信息,打開本地文件。                         ////  對 GET200 數據域傳輸來的數據保存到本地文件中。                     ////  收到 GET300 命令,關閉本地文件,傳輸過程結束。                     ////                                             ////  文件傳輸服務端程序:                                  ////  sfd  在 accept() 后獲取的新的客戶端連接通道描述符                   ////  path 準備保存本地文件的路徑信息                            ////  fileName 根據接收報文中的文件名稱與本地路徑拼串而得到的返回文件信息          ////  timeout  數據傳輸需要使用的延時參數                          ////                                             ////  返回數據:                                       ////  0 ---- 文件接收成功                                  ////  -2 -- 文件無法創建,打開文件名稱失敗                          ////  -1 -- 文件內容內容保存失敗                               ////  ====================================================================================== ////int srv_get_recvFile(int sfd , char *path, char *fileName, int timeout ){  int fd = -1;   int  blknum = 0, maxBlk=0 ;  char  tfile[NFILE+1], bfile[NFILE+1];  char  *ptr;   long  fsize = 0;   int  chkflg = 0;    memset(tfile, 0x00, sizeof(tfile));   while (1){    memset(&ncb, 0x00, sizeof (struct tcpBuffer));     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 后面的命令控制字,下面分析該控制字進行工作       case 100 : // 開始接收文件,打開本地文件         wLog(LOGINFO, "接收管理報文[%s]成功", ncb.buff );        // 對于接收到的第一條命令,打印該控制命令的全部內容         ptr = strchr(ncb.buff, ':');        if(ptr) memcpy(tfile, ncb.buff+19, ptr - (char *)ncb.buff - 19);        else  strcpy(tfile, ncb.buff+19);        // 獲取傳輸來的文件名稱         ptr = strrchr(tfile, '/');        if(ptr) strcpy(bfile, ptr+1);        else  strcpy(bfile, tfile);        // 檢查傳輸來文件名稱中的路徑信息,得到基本文件名稱,將前面的路徑        // 信息全部剔除,以保證本地文件的安全。         if( (ptr = strrchr(ncb.buff , ':') ) != NULL ) maxBlk = atoi (ptr +1);         if( path ) sprintf(fileName, "%s/%s", path, bfile);        else    strcpy(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 ;      case 200 :  // 保存文件內容        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;        }        else fsize += ncb.wlen ;         break ;      case 300 : // 文件傳輸結束        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 );   return chkflg ;}  //  ============================= 客戶端使用 多文件發送程序 =============================== //////                                              ////  socket 方式文件發送程序,根據輸入的 netinfo 建立通信通道,然后按照以下要求發送文件   ////  GET100 發送文件基本信息                                 ////  GET200 發送文件內容,根據要求循環執行,......                      ////  GET300 數據發送結束                                   ////                                              ////  ======================================================================================= //// //// 在建立好的文件傳輸通道上,將一個文件數據發送到服務端,傳輸后,不需要關閉傳輸通道。//int  cli_mget_sendFile(int sfd, char *localFile, char *remoteFile, int blockSize, int timeout ){  int  fd = -1;   struct stat sb;  int  iRet ;  int  chkflg = 0 ;  int  maxBlk, blknum = 0;  char  *ftr;   long  start;  long  fsize;   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;    goto mSend_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 (struct tcpBuffer));   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;    goto mSend_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;    goto mSend_END;  }  wLog(LOGINFO,"接到返回數據 [%s]成功", ncb.rcvcmd );    while (1)  {    blknum ++;    memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));    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;      goto mSend_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;      goto mSend_END;    }  }   memset(&ncb , 0x00 , sizeof (struct tcpBuffer ));   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;    goto mSend_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;    goto mSend_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);  // 關閉本文描述符和通信連接通道描述符   return chkflg; } // ============================================= 多文件處理函數 ====================================== ////                                                   ////                                                   //// 多文件發送服務程序,本程序對使用 ":" 分隔的文件信息自動進行分解,然后將每一個文件          //// 使用上述函數完成推送工作,在啊全部文件發送完畢后,程序將發出 get500 傳輸結束命令。         ////                                                   ///////////////////////////////////////////////////////////////////////////////////////////////////////////int  cli_getm_sendFile(char *netinfo, char *sLocalFile, int blockSize, int timeout){  int sfd = -1;   int  iRet ;  int  chkflg = 0 ;   struct cli_getm_sendFile{    char  lFile[NFILE+1];   // 本地文件名稱    char  rFile[NFILE+1];   // 遠程文件名稱  }mSnd;   char  *qlist , *ptr ;  char  *ftr;  int  fnum = 0;  long  start ;   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 (struct tcpBuffer ));  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;    goto cli_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;    goto cli_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);  // 關閉本文描述符和通信連接通道描述符   return chkflg;}  //  ============================ 服務端使用 多文件傳輸程序 =============================== //////                                             ////  socket 文件接收服務程序,對收到的通信報文進行分析。                  ////  在收到 GET100 命令后,將該數據域中的文件名稱與本地路徑拼寫得到完整的文件        ////         路徑信息,打開本地文件。                         ////  對 GET200 數據域傳輸來的數據保存到本地文件中。                     ////  收到 GET300 命令,關閉當前傳輸文件。                          ////  收到 get500 命令,TCP 文件傳輸過程結束,退出程序。                   ////                                             ////  文件傳輸服務端程序:                                  ////  sfd  在 accept() 后獲取的新的客戶端連接通道描述符                   ////  path 準備保存本地文件的路徑信息                            ////  fileName 根據接收報文中的文件名稱與本地路徑拼串而得到的返回文件信息          ////  timeout  數據傳輸需要使用的延時參數                          ////                                             ////  返回數據:                                       ////  0 ---- 文件接收成功                                  ////  -2 -- 文件無法創建,打開文件名稱失敗                          ////  -1 -- 文件內容內容保存失敗                               ////                                             ////  文件傳輸過程中,上傳的文件名稱有客戶端提供,但是文件保存路徑由服務器控制,以充分保證  ////  服務器文件系統的安全,避免服務器上的文件被客戶端上傳文件惡意覆蓋。           ////                                             ////  ====================================================================================== ////int srv_mget_recvFile(int sfd , char *path, int timeout ){  int fd = -1;   int  blknum = 0 , maxBlk = 0 ;  char  localFile[NFILE+1];  char  tfile[NFILE+1], bfile[NFILE+1];  char  *ptr;   long  fsize = 0;  long  start = time(NULL);   int  chkflg = 0;  int  fnum = 0;    memset(tfile, 0x00, sizeof(tfile));   while (1){    memset(&ncb, 0x00, sizeof (struct tcpBuffer));     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 后面的命令控制字,下面分析該控制字進行工作       case 100 : // 開始接收文件,打開本地文件        blknum = maxBlk = 0 ;        wLog(LOGINFO, "接收管理報文[%s]成功", ncb.buff );        // 對于接收到的第一條命令,打印該控制命令的全部內容         ptr = strchr(ncb.buff, ':');        if(ptr) memcpy(tfile, ncb.buff+19, ptr - (char *)ncb.buff - 19);        else  strcpy(tfile, ncb.buff+19);        // 獲取傳輸來的文件名稱         ptr = strrchr(tfile, '/');        if(ptr) strcpy(bfile, ptr+1);        else  strcpy(bfile, tfile);        // 檢查傳輸來文件名稱中的路徑信息,得到基本文件名稱,將前面的路徑        // 信息全部剔除,以保證本地文件的安全。當傳輸文件名稱帶有 ".." 標志        // 的時候,將會對服務器文件系統產生影響,需要保證該問題不會出現。         if( (ptr = strrchr(ncb.buff , ':') ) != NULL ) maxBlk = atoi (ptr +1);        // 從命令報文中得到文件傳輸塊信息。         if( path ) sprintf(localFile, "%s/%s", path, bfile);        else    strcpy(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 ;      case 200 :  // 保存文件內容        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;        }        else fsize += ncb.wlen ;         break ;      case 300 : // 文件傳輸結束        if( !maxBlk )          wLog(LOGINFO, " 文件[%s]成功接收,共 [%d] 傳輸塊 ", localFile, blknum );        else          wLog(LOGERROR,"文件[%s]接收結束,差錯 [%d] 傳輸塊 ", localFile , maxBlk );         close(fd);        break ;      case 500 : // 通信處理結束        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 );   return chkflg ;}  #endif

以上就是本文的全部內容,希望對大家的學習有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品视频26uuu| 国产日韩欧美夫妻视频在线观看| 中文字幕欧美日韩精品| 欧美成人一区在线| 国产丝袜一区二区三区免费视频| 一本色道久久综合狠狠躁篇的优点| 欧美孕妇与黑人孕交| 中文字幕av一区中文字幕天堂| 97国产精品人人爽人人做| 国产日韩在线精品av| 亚洲欧美日韩精品久久亚洲区| 欧美性猛交xxxx乱大交3| 国产精品96久久久久久| 久久精品亚洲94久久精品| 日韩av成人在线| 性日韩欧美在线视频| 国产精品视频久久久久| 成人免费观看网址| 国产精品亚洲视频在线观看| 日韩精品在线观看网站| 日韩亚洲欧美成人| 69久久夜色精品国产69乱青草| 国产视频欧美视频| 亚洲激情视频在线| 97香蕉久久超级碰碰高清版| 91国产美女在线观看| 亚洲女人被黑人巨大进入| 久久99视频免费| 韩国v欧美v日本v亚洲| 日韩亚洲精品视频| 美女精品久久久| 91国偷自产一区二区三区的观看方式| 性色av香蕉一区二区| 欧美视频在线免费| 久久综合网hezyo| 黑人巨大精品欧美一区二区三区| 亚洲欧美中文日韩在线| 亚洲欧美制服第一页| 不卡在线观看电视剧完整版| 最新69国产成人精品视频免费| 精品视频偷偷看在线观看| 亚洲精品国产综合久久| 国模极品一区二区三区| 97视频在线观看免费高清完整版在线观看| 亚洲aa中文字幕| 国产成人在线播放| 亚洲欧美福利视频| 播播国产欧美激情| 亚洲一区二区少妇| 日韩在线www| 另类少妇人与禽zozz0性伦| 国产精品入口免费视频一| 欧美国产亚洲精品久久久8v| 北条麻妃99精品青青久久| 久久精品久久久久电影| 国产精品第二页| 日韩不卡在线观看| 国产一区二区丝袜| 亚洲精品网址在线观看| 日韩精品中文字幕在线观看| 91中文在线观看| 亚洲色图美腿丝袜| 亚洲激情电影中文字幕| 亚洲综合在线中文字幕| 自拍偷拍亚洲区| 久久天堂av综合合色| 久久中文字幕在线| 亚洲aⅴ日韩av电影在线观看| 中文字幕精品在线| 亚洲天堂第二页| 国产精品中文字幕在线观看| 色偷偷噜噜噜亚洲男人的天堂| 亚洲娇小xxxx欧美娇小| 色综合久久久888| 成人深夜直播免费观看| 亚洲美女精品成人在线视频| 国内精品久久久久久久| 精品久久久久久中文字幕| 2018日韩中文字幕| 亚洲国产日韩欧美在线图片| 欧美日韩中文字幕综合视频| 国产手机视频精品| 91成人天堂久久成人| 日韩有码片在线观看| www高清在线视频日韩欧美| 国产精品久久久久久久av大片| 国色天香2019中文字幕在线观看| 欧美激情在线一区| 国产精品一二区| 精品久久久久久亚洲精品| 18一19gay欧美视频网站| 欧美限制级电影在线观看| 国产成人精品日本亚洲| 亚洲国产美女精品久久久久∴| 成人国产在线视频| 色噜噜狠狠狠综合曰曰曰| 国产成人高清激情视频在线观看| 中文字幕精品av| 日韩网站在线观看| 国产欧美精品在线播放| 91精品国产综合久久久久久蜜臀| 日韩激情视频在线| 久热爱精品视频线路一| 亚洲一级黄色片| 国产午夜精品全部视频播放| 亚洲欧美制服综合另类| 51精品国产黑色丝袜高跟鞋| 国产成人综合久久| 欧美视频免费在线| 欧美日韩亚洲视频| 亚洲丝袜在线视频| 欧美日韩国产精品专区| 亚洲欧美制服综合另类| 亚洲精品wwww| 精品国产一区二区三区在线观看| 亚洲最大av网| 日本不卡视频在线播放| 亚洲自拍高清视频网站| 国产99久久精品一区二区永久免费| 在线视频免费一区二区| 欧美国产日韩一区二区三区| 亚洲日本欧美中文幕| 成人性教育视频在线观看| 国产精品久久99久久| 日韩有码在线电影| 亚洲午夜精品视频| 久久人人爽人人爽爽久久| 欧美国产在线电影| 亚洲香蕉在线观看| 国产精品自拍偷拍| 国产精品欧美日韩| 久久亚洲精品一区二区| 精品少妇一区二区30p| 性日韩欧美在线视频| 日韩av高清不卡| 2019中文字幕全在线观看| 俺去亚洲欧洲欧美日韩| 国产在线拍偷自揄拍精品| 91午夜在线播放| 亚洲国语精品自产拍在线观看| 亚洲精品网址在线观看| 亚洲精品视频在线观看视频| 欧美裸身视频免费观看| 亚洲午夜久久久久久久| 国产精品视频1区| 日韩视频精品在线| 日韩av影片在线观看| 成人在线免费观看视视频| 欧美中文字幕视频在线观看| 亚洲男女性事视频| 久久最新资源网| 欧美一级淫片videoshd| 亚洲美女动态图120秒| 亚洲女人天堂成人av在线| 在线看福利67194| 久久久久成人网| 91天堂在线视频| 国产精品香蕉在线观看| 亚洲欧洲国产精品| 国产精品日韩在线| 91视频国产精品| 国产偷国产偷亚洲清高网站| 4444欧美成人kkkk| 久久精品视频导航|