版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、#ifndef CLIENT_H_#define CLIENT_H_#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define INVALID_SOCKET-1#define FTP_APIint#define MAX_PATH260#define traceprintf#define FTP_PARAM_BASE#define FTP_DEFAULT_PORT21/FT
2、P默認(rèn)端口號(hào)#define FTP_DEFAULT_BUFFER1024*4/FTP下載緩沖默認(rèn)大小#define FTP_DEFAULT_PATH/mnt/dvs/FTP默認(rèn)保存路徑#define FTP_COMMAND_BASE1000#define FTP_COMMAND_ENDFTP_COMMAND_BASE + 30#define FTP_COMMAND_USERNAMEFTP_COMMAND_BASE + 1/用戶名#define FTP_COMMAND_PASSWORDFTP_COMMAND_BASE + 2/密碼#define FTP_COMMAND_QUITFTP_COMMA
3、ND_BASE + 3/退出#define FTP_COMMAND_CURRENT_PATHFTP_COMMAND_BASE + 4/ 獲取文件路徑#define FTP_COMMAND_TYPE_MODEFTP_COMMAND_BASE + 5/ 改變傳輸模式#define FTP_COMMAND_PSAV_MODEFTP_COMMAND_BASE + 6/ 被動(dòng)端口模式#define FTP_COMMAND_DIRFTP_COMMAND_BASE + 7/ 獲取文件列表#define FTP_COMMAND_CHANGE_DIRECTORY FTP_COMMAND_BASE + 8/ 改變
4、路徑#define FTP_COMMAND_DELETE_FILEFTP_COMMAND_BASE + 9/ 刪除文件#define FTP_COMMAND_DELETE_DIRECTORY FTP_COMMAND_BASE + 10/ 刪除目錄/文件夾#define FTP_COMMAND_CREATE_DIRECTORY FTP_COMMAND_BASE + 11/ 創(chuàng)建目錄/文件夾#define FTP_COMMAND_RENAME_BEGIN FTP_COMMAND_BASE +12/ 開始重命名#define FTP_COMMAND_RENAME_END FTP_COMMAND_BA
5、SE + 13/ 重命名結(jié)束#define FTP_COMMAND_FILE_SIZEFTP_COMMAND_BASE + 14/ 獲取文件大小#define FTP_COMMAND_DOWNLOAD_POSFTP_COMMAND_BASE + 15/ 下載文件從指定位置開始#define FTP_COMMAND_DOWNLOAD_FILEFTP_COMMAND_BASE + 16/ 下載文件#define FTP_COMMAND_UPLOAD_FILEFTP_COMMAND_BASE + 17/ 上傳文件#define FTP_COMMAND_APPEND_FILEFTP_COMMAND_B
6、ASE + 18/ 追加上載文件/* 登陸步驟login2Server|inputUserName|inputPassWord| 具體操作| quit*/class CFTPManager public :enum type binary = 0 x31,ascii,;CFTPManager(void);virtual CFTPManager(void);/ ! 登陸服務(wù)器FTP_API login2Server(const std:string &serverIP);/ !輸入用戶名FTP_API inputUserName(const std:string &userName);/ !輸入
7、密碼FTP_API inputPassWord(const std:string &password);/ !退出FTPFTP_API quitServer(void);/ !命令: PWDconst std:string PWD();/ !設(shè)置傳輸格式 2進(jìn)制 還是ascii方式傳輸FTP_API setTransferMode(type mode);/ !設(shè)置為被動(dòng)模式const std:string Pasv();/ ! 命令: DIRconst std:string Dir(const std:string &path);/ !命令 : CDFTP_API CD(const std:s
8、tring &path);/ !刪除文件FTP_API DeleteFile(const std:string &strRemoteFile);/ ! 刪除文件夾/目錄FTP_API DeleteDirectory(const std:string &strRemoteDir);/ ! 創(chuàng)建目錄/文件夾FTP_API CreateDirectory(const std:string &strRemoteDir);/ !重命名FTP_API Rename(const std:string &strRemoteFile, const std:string &strNewFile);/ !獲取文件大
9、小long getFileLength(const std:string &strRemoteFile);/ !關(guān)閉連接void Close(int sock);/ 下載文件FTP_API Get(const std:string &strRemoteFile, const std:string &strLocalFile);/ 上載文件 支持?jǐn)嚯妭魉头绞紽TP_API Put(const std:string &strRemoteFile, const std:string &strLocalFile);private:/ !合成發(fā)送到服務(wù)器的命令const std:string parse
10、Command(const unsigned int command, const std:string &strParam);/ ! 建立連接FTP_API Connect(int socketfd, const std:string &serverIP, unsigned int nPort);/ ! 返回服務(wù)器信息const std:string serverResponse(int sockfd);/ !獲取服務(wù)器數(shù)據(jù)FTP_API getData(int fd, char *strBuf, unsigned long length);/ !發(fā)送命令FTP_API Send(int f
11、d, const std:string &cmd);/ !發(fā)送命令FTP_API Send(int fd, const char *cmd, const size_t len);/ !建立數(shù)據(jù)連接FTP_API createDataLink(int data_fd);/ !解析PASV模式返回的字符串獲取FTP端口號(hào)和FTP服務(wù)器IPFTP_API ParseString(std:list strArray, unsigned long & nPort ,std:string & strServerIp);/ 打開本地文件FILE *createLocalFile(const std:stri
12、ng &strLocalFile);/ 下載文件 FTP_API downLoad(const std:string &strRemoteFile, const std:string &strLocalFile, const int pos = 0, const unsigned int length = 0);/ 解析返回ftp命令的值FTP_API parseResponse(const std:string &str);private:/!控制連接套接字intm_cmdSocket;/ !當(dāng)前用戶名std:string m_strUserName;/ !當(dāng)前用戶密碼std:string
13、m_strPassWord;/ !服務(wù)器的IPstd:string m_strServerIP;/ !服務(wù)器Portunsigned int m_nServerPort;/ !服務(wù)器回應(yīng)信息緩存std:string m_strResponse;/ !保存命令參數(shù)std:string m_commandStr;/ !當(dāng)前使用的命令參數(shù)unsigned int m_nCurrentCommand;/ !是否登陸標(biāo)志。boolm_bLogin;#endif/源代碼/ author: fuyl/ 2011-04-06-13:58#include ./Source/FTPManager.hstatic
14、int SplitString( std:string strSrc, std:list &strArray , std:string strFlag)int pos = 1; while(pos = (int)strSrc.find_first_of(strFlag.c_str() 0) strArray.insert(strArray.end(), strSrc.substr(0 , pos);strSrc = strSrc.substr(pos + 1, strSrc.length() - pos - 1); strArray.insert(strArray.end(), strSrc.
15、substr(0, strSrc.length();return 0; CFTPManager:CFTPManager(void): m_bLogin(false)m_cmdSocket = socket(AF_INET, SOCK_STREAM, 0);CFTPManager:CFTPManager(void)std:string strCmdLine = parseCommand(FTP_COMMAND_QUIT, );Send(m_cmdSocket, strCmdLine.c_str();close(m_cmdSocket);m_bLogin = false;FTP_API CFTPM
16、anager:login2Server(const std:string &serverIP)std:string strPort;int pos = serverIP.find_first_of(:);if (pos 0)strPort = serverIP.substr(pos + 1, serverIP.length() - pos);elsepos = serverIP.length();strPort = FTP_DEFAULT_PORT;m_strServerIP = serverIP.substr(0, pos);m_nServerPort = atol(strPort.c_st
17、r();trace(IP: %s port: %dn, m_strServerIP.c_str(), m_nServerPort);if (Connect(m_cmdSocket, m_strServerIP, m_nServerPort) 0)return -1;m_strResponse = serverResponse(m_cmdSocket);printf(Response: %s, m_strResponse.c_str();returnparseResponse(m_strResponse);FTP_API CFTPManager:inputUserName(const std:s
18、tring &userName)std:string strCommandLine = parseCommand(FTP_COMMAND_USERNAME, userName);m_strUserName = userName;if (Send(m_cmdSocket, strCommandLine) 0)return -1;m_strResponse = serverResponse(m_cmdSocket);printf(Response: %sn, m_strResponse.c_str();return parseResponse(m_strResponse);FTP_API CFTP
19、Manager:inputPassWord(const std:string &password)std:string strCmdLine = parseCommand(FTP_COMMAND_PASSWORD, password);m_strPassWord = password;if (Send(m_cmdSocket, strCmdLine) 0)return -1;elsem_bLogin = true;m_strResponse = serverResponse(m_cmdSocket);printf(Response: %sn, m_strResponse.c_str();ret
20、urn parseResponse(m_strResponse);FTP_API CFTPManager:quitServer(void)std:string strCmdLine = parseCommand(FTP_COMMAND_QUIT, );if (Send(m_cmdSocket, strCmdLine) 0)return -1;elsem_strResponse = serverResponse(m_cmdSocket);printf(Response: %sn, m_strResponse.c_str();return parseResponse(m_strResponse);
21、const std:string CFTPManager:PWD()std:string strCmdLine = parseCommand(FTP_COMMAND_CURRENT_PATH, );if (Send(m_cmdSocket, strCmdLine.c_str() 0)return ;elsereturn serverResponse(m_cmdSocket);FTP_API CFTPManager:setTransferMode(type mode)std:string strCmdLine;switch (mode)case binary:strCmdLine = parse
22、Command(FTP_COMMAND_TYPE_MODE, I);break;case ascii:strCmdLine = parseCommand(FTP_COMMAND_TYPE_MODE, A);break;default:break;if (Send(m_cmdSocket, strCmdLine.c_str() 0)assert(false);elsem_strResponse = serverResponse(m_cmdSocket);printf(Response: %s, m_strResponse.c_str();return parseResponse(m_strRes
23、ponse);const std:string CFTPManager:Pasv()std:string strCmdLine = parseCommand(FTP_COMMAND_PSAV_MODE, );if (Send(m_cmdSocket, strCmdLine.c_str() 0)return ;elsem_strResponse = serverResponse(m_cmdSocket);return m_strResponse;const std:string CFTPManager:Dir(const std:string &path)int dataSocket = soc
24、ket(AF_INET, SOCK_STREAM, 0);if (createDataLink(dataSocket) 0)return ;/ 數(shù)據(jù)連接成功std:string strCmdLine = parseCommand(FTP_COMMAND_DIR, path);if (Send(m_cmdSocket, strCmdLine) 0)trace(Response: %sn, serverResponse(m_cmdSocket).c_str();close(dataSocket);return ;elsetrace(Response: %sn, serverResponse(m_c
25、mdSocket).c_str();m_strResponse = serverResponse(dataSocket);trace(Response: n%sn, m_strResponse.c_str();close(dataSocket);return m_strResponse;FTP_API CFTPManager:CD(const std:string &path)assert(m_cmdSocket != INVALID_SOCKET);std:string strCmdLine = parseCommand(FTP_COMMAND_CHANGE_DIRECTORY, path)
26、;if (Send(m_cmdSocket, strCmdLine) 0)return -1;m_strResponse = serverResponse(m_cmdSocket);trace(Response: %sn, m_strResponse.c_str();return parseResponse(m_strResponse);FTP_API CFTPManager:DeleteFile(const std:string &strRemoteFile)assert(m_cmdSocket != INVALID_SOCKET);std:string strCmdLine = parse
27、Command(FTP_COMMAND_DELETE_FILE, strRemoteFile);if (Send(m_cmdSocket, strCmdLine) 0)return -1;m_strResponse = serverResponse(m_cmdSocket);printf(Response: %sn, m_strResponse.c_str();return parseResponse(m_strResponse);FTP_API CFTPManager:DeleteDirectory(const std:string &strRemoteDir)assert(m_cmdSoc
28、ket != INVALID_SOCKET);std:string strCmdLine = parseCommand(FTP_COMMAND_DELETE_DIRECTORY, strRemoteDir);if (Send(m_cmdSocket, strCmdLine) 0)return -1;m_strResponse = serverResponse(m_cmdSocket);trace(Response: %sn, m_strResponse.c_str();return parseResponse(m_strResponse);FTP_API CFTPManager:CreateD
29、irectory(const std:string &strRemoteDir)assert(m_cmdSocket != INVALID_SOCKET);std:string strCmdLine = parseCommand(FTP_COMMAND_CREATE_DIRECTORY, strRemoteDir);if (Send(m_cmdSocket, strCmdLine) 0)return -1;m_strResponse = serverResponse(m_cmdSocket);trace(Response: %sn, m_strResponse.c_str();return p
30、arseResponse(m_strResponse);FTP_API CFTPManager:Rename(const std:string &strRemoteFile, const std:string &strNewFile)assert(m_cmdSocket != INVALID_SOCKET);std:string strCmdLine = parseCommand(FTP_COMMAND_RENAME_BEGIN, strRemoteFile);Send(m_cmdSocket, strCmdLine);trace(Response: %sn, serverResponse(m
31、_cmdSocket).c_str();Send(m_cmdSocket, parseCommand(FTP_COMMAND_RENAME_END, strNewFile);m_strResponse = serverResponse(m_cmdSocket);trace(Response: %sn, m_strResponse.c_str();return parseResponse(m_strResponse);long CFTPManager:getFileLength(const std:string &strRemoteFile)assert(m_cmdSocket != INVAL
32、ID_SOCKET);std:string strCmdLine = parseCommand(FTP_COMMAND_FILE_SIZE, strRemoteFile);if (Send(m_cmdSocket, strCmdLine) 0)return -1;m_strResponse = serverResponse(m_cmdSocket);trace(Response: %sn, m_strResponse.c_str();std:string strData = m_strResponse.substr(0, 3);unsigned long val = atol(strData.
33、c_str();if (val = 213)strData = m_strResponse.substr(4);trace(strData: %sn, strData.c_str();val = atol(strData.c_str();return val;return -1;void CFTPManager:Close(int sock)shutdown(sock, SHUT_RDWR);close(sock);sock = INVALID_SOCKET;FTP_API CFTPManager:Get(const std:string &strRemoteFile, const std:s
34、tring &strLocalFile)return downLoad(strRemoteFile, strLocalFile);FTP_API CFTPManager:Put(const std:string &strRemoteFile, const std:string &strLocalFile)std:string strCmdLine;const unsigned long dataLen = FTP_DEFAULT_BUFFER;char strBufdataLen = 0;unsigned long nSize = getFileLength(strRemoteFile);un
35、signed long nLen = 0;/ struct stat sBuf;/ / assert(stat(strLocalFile.c_str(), &sBuf) = 0);/ trace(size: %dn, sBuf.st_size);FILE *pFile = fopen(strLocalFile.c_str(), rb); / 以只讀方式打開 且文件必須存在assert(pFile != NULL);int data_fd = socket(AF_INET, SOCK_STREAM, 0);assert(data_fd != -1);if (createDataLink(data
36、_fd) 0)return -1;if (nSize = -1)strCmdLine = parseCommand(FTP_COMMAND_UPLOAD_FILE, strRemoteFile);elsestrCmdLine = parseCommand(FTP_COMMAND_APPEND_FILE, strRemoteFile);if (Send(m_cmdSocket, strCmdLine) 0)Close(data_fd);return -1;trace(Response: %sn, serverResponse(m_cmdSocket).c_str();fseek(pFile, n
37、Size, SEEK_SET);while (!feof(pFile)nLen = fread(strBuf, 1, dataLen, pFile);if (nLen 0)break;if (Send(data_fd, strBuf) 0)Close(data_fd);return -1;trace(Response: %sn, serverResponse(data_fd).c_str();Close(data_fd);trace(Response: %sn, serverResponse(m_cmdSocket).c_str();fclose(pFile);return 0;const s
38、td:string CFTPManager:parseCommand(const unsigned int command, const std:string &strParam)if (command FTP_COMMAND_END)return ;std:string strCommandLine;m_nCurrentCommand = command;m_commandStr.clear();switch (command)case FTP_COMMAND_USERNAME:strCommandLine = USER ;break;case FTP_COMMAND_PASSWORD:st
39、rCommandLine = PASS ;break;case FTP_COMMAND_QUIT:strCommandLine = QUIT ;break;case FTP_COMMAND_CURRENT_PATH:strCommandLine = PWD ;break;case FTP_COMMAND_TYPE_MODE:strCommandLine = TYPE ;break;case FTP_COMMAND_PSAV_MODE:strCommandLine = PASV ;break;case FTP_COMMAND_DIR:strCommandLine = LIST ;break;ca
40、se FTP_COMMAND_CHANGE_DIRECTORY:strCommandLine = CWD ;break;case FTP_COMMAND_DELETE_FILE:strCommandLine = DELE ;break;case FTP_COMMAND_DELETE_DIRECTORY:strCommandLine = RMD ;break;case FTP_COMMAND_CREATE_DIRECTORY:strCommandLine = MKD ;break;case FTP_COMMAND_RENAME_BEGIN:strCommandLine = RNFR ;break
41、;case FTP_COMMAND_RENAME_END:strCommandLine = RNTO ;break;case FTP_COMMAND_FILE_SIZE:strCommandLine = SIZE ;break;case FTP_COMMAND_DOWNLOAD_FILE:strCommandLine = RETR ;break;case FTP_COMMAND_DOWNLOAD_POS:strCommandLine = REST ;break;case FTP_COMMAND_UPLOAD_FILE:strCommandLine = STOR ;break;case FTP_
42、COMMAND_APPEND_FILE:strCommandLine = APPE ;break;default :break;strCommandLine += strParam;strCommandLine += rn;m_commandStr = strCommandLine;trace(parseCommand: %sn, m_commandStr.c_str();return m_commandStr;FTP_API CFTPManager:Connect(int socketfd, const std:string &serverIP, unsigned int nPort)if
43、(socketfd = INVALID_SOCKET)return -1;unsigned int argp = 1;int error = -1;int len = sizeof(int);struct sockaddr_in addr;bool ret = false;timeval stime;fd_set set;ioctl(socketfd, FIONBIO, &argp); /設(shè)置為非阻塞模式memset(&addr, 0, sizeof(struct sockaddr_in);addr.sin_family = AF_INET;addr.sin_port= htons(nPort
44、);addr.sin_addr.s_addr = inet_addr(serverIP.c_str();bzero(&(addr.sin_zero), 8);trace(Address: %s %dn, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port);if (connect(socketfd, (struct sockaddr*)&addr, sizeof(struct sockaddr) = -1) /若直接返回 則說明正在進(jìn)行TCP三次握手stime.tv_sec = 20; /設(shè)置為1秒超時(shí)stime.tv_usec = 0;FD_ZERO(
45、&set);FD_SET(socketfd, &set);if (select(socketfd + 1, NULL, &set, NULL, &stime) 0) /在這邊等待 阻塞 返回可以讀的描述符 或者超時(shí)返回0 或者出錯(cuò)返回-1getsockopt(socketfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t*)&len);if (error = 0)ret = true;elseret = false;elsetrace(Connect Immediately!n);ret = true;argp = 0;ioctl(socketfd, FI
46、ONBIO, &argp);if (!ret)close(socketfd);fprintf(stderr, cannot connect server!n);return -1;/fprintf(stdout, Connect!n);return 0;const std:string CFTPManager:serverResponse(int sockfd)if (sockfd = INVALID_SOCKET)return ;int nRet = -1;char bufMAX_PATH = 0;m_strResponse.clear();while (nRet = getData(soc
47、kfd, buf, MAX_PATH) 0)bufMAX_PATH - 1 = 0;m_strResponse += buf;return m_strResponse;FTP_API CFTPManager:getData(int fd, char *strBuf, unsigned long length)assert(strBuf != NULL);if (fd = INVALID_SOCKET)return -1;memset(strBuf, 0, length);timeval stime;int nLen;stime.tv_sec = 1;stime.tv_usec = 0;fd_s
48、etreadfd;FD_ZERO( &readfd );FD_SET(fd, &readfd );if (select(fd + 1, &readfd, 0, 0, &stime) 0)if (nLen = recv(fd, strBuf, length, 0) 0)return nLen;elsereturn -2;return 0;FTP_API CFTPManager:Send(int fd, const std:string &cmd)if (fd = INVALID_SOCKET)return -1;return Send(fd, cmd.c_str(), cmd.length();
49、FTP_API CFTPManager:Send(int fd, const char *cmd, const size_t len)if(FTP_COMMAND_USERNAME != m_nCurrentCommand) &(FTP_COMMAND_PASSWORD != m_nCurrentCommand)&(!m_bLogin)return -1;timeval timeout;timeout.tv_sec = 1;timeout.tv_usec = 0;fd_set writefd;FD_ZERO(&writefd); FD_SET(fd, &writefd);if(select(f
50、d + 1, 0, &writefd , 0 , &timeout) 0)size_t nlen = len; int nSendLen = 0; while (nlen 0) nSendLen = send(fd, cmd , (int)nlen , 0);if(nSendLen = -1) return -2; nlen = nlen - nSendLen;cmd += nSendLen;return 0;return -1;FTP_API CFTPManager:createDataLink(int data_fd)assert(data_fd != INVALID_SOCKET);st
51、d:string strData;unsigned long nPort = 0 ;std:string strServerIp ; std:list strArray ;std:string parseStr = Pasv();if (parseStr.size() = 0)return -1;/trace(parseInfo: %sn, parseStr.c_str();size_t nBegin = parseStr.find_first_of();size_t nEnd = parseStr.find_first_of();strData = parseStr.substr(nBegi
52、n + 1, nEnd - nBegin - 1);/trace(ParseAfter: %sn, strData.c_str();if( SplitString( strData , strArray , , ) 0)return -1;if( ParseString( strArray , nPort , strServerIp) 0)return -1;/trace(nPort: %ld IP: %sn, nPort, strServerIp.c_str();if (Connect(data_fd, strServerIp, nPort) 0)return -1;return 0;FTP_API CFTPManager:ParseString(std:list strArray, unsigned long & nPort ,std:string & strServerIp)if (strArray.size() 6 )return -1 ;std
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 存量住房回購協(xié)議
- 信用卡分期付款協(xié)議
- 國內(nèi)沿海集裝箱貨運(yùn)代理合作條款
- 廣告公司拍攝合同
- 2024年房屋買賣合同協(xié)議書樣本
- 2024年圖文廣告設(shè)計(jì)制作合同
- 學(xué)生貸款合同格式
- 石油化工工程承攬合同
- 保潔服務(wù)合同范文全書
- 蘇教版小學(xué)數(shù)學(xué)三年級下冊《認(rèn)識(shí)幾分之一》公開課課件
- 幼兒園成語故事《背水一戰(zhàn)》課件
- IATF16949內(nèi)部審核員培訓(xùn)結(jié)業(yè)考核試題附答案
- 中職-技能高考-機(jī)械制圖
- MOOC 中國電影經(jīng)典影片鑒賞-北京師范大學(xué) 中國大學(xué)慕課答案
- 國外幼兒常規(guī)教育現(xiàn)狀研究綜述
- CJT 358-2019 非開挖工程用聚乙烯管
- 20K607 防排煙及暖通防火設(shè)計(jì)審查與安裝
- 小學(xué)英語數(shù)字化教學(xué)策略創(chuàng)新與實(shí)踐
- 護(hù)理人體美第四章
- 中國天眼完整版本
- 機(jī)器人社團(tuán)考試試卷附有答案
評論
0/150
提交評論