C++文件上傳、下載對象。本站提示廣大學習愛好者:(C++文件上傳、下載對象)文章只能為提供參考,不一定能成為您想要的結果。以下是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" #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
以上就是本文的全體內容,願望對年夜家的進修有所贊助。