先贴一下 类声明: // // name: paco // email: mk00709@gmail.com // // #pragma comment(lib, "Winmm.lib") #ifndef _WINSOCKAPI_ #define _WINSOCKAPI_ #include <winsock2.h> #endif typedef void (*PopFtpMessage)(int code, char* recvData); //FTP消息回调 typedef void (*FtpRecvDirData)(char* recvDirData); //FTP 目录数据 typedef void (*FtpRecvFileData)(byte* recvFileData, unsigned long iPos, unsigned long iLength, char *fileName); //FTP 目录数据 enum FtpCommand {abor,allo,appe,cudp,list,pass,port,quit,retr,stor,syst,mode,type,user,pasv,cwd,size,mkd,dele,rmd,help,noop,rest,rnto}; enum FtpCharSet{gb2312,utf8}; typedef struct _CmdPacket //命令数据包 { FtpCommand ftpcmd; char param[256]; }CmdPacket; class FtpClientControl { public: FtpClientControl(); FtpClientControl(PopFtpMessage pFunc); ~FtpClientControl(); bool Init(char* ip, int port = 21); bool SubmitCommand(FtpCommand ftpCmd, char* param); void SubmitData(char* pSubmitData); int Login(char* pUserName, char* pPassword); //返回-1:提交失败. 0:成功.1:找不到用户.2:密码错误 int Pasv(); int Size(char *pFileName); bool Type(char *pType); bool CWD(char *pPath); bool Quit(); bool Dele(char *pFileName); bool Rmd(char *pDirName); bool Mkd(char *pDirName); bool Rest(char *pNum); int GetPasvPort(char pasvData[256]); //拆解PASV命令后,端口信息 char* GetErrorMsg(); void ReadRsp(); void RegiestMsg(PopFtpMessage pFunc) { popFtpMsg = pFunc; } bool PrintData(int iPos); void SetReturnFlagState(); bool GetReturnFlagState(); private: WSADATA m_wsaData; SOCKET m_s, m_dataSocket; SOCKADDR_IN m_ServerAddr; PopFtpMessage popFtpMsg; //回调函数成员变量 char m_strPath[256]; //路径 public: int m_Error; //错误码 char m_strError[256]; //错误信息 char m_recvData[4096];//命令返回信息 int m_code; //命令返回代码 char m_user[256]; //用户名 char m_pw[256]; //密码 char m_ip[16]; //服务器IP地址 int m_port; //端口 int m_pasvPort; //PASV命令返回端口 bool m_bReturnFlag; //设置返回标志 }; class FtpClientData { public: FtpClientData(); ~FtpClientData(); bool InitConnect(char* ip, int port); void RecvDirData(); void RecvFileDate(); int CloseConnect(); void RegiestDirFun(FtpRecvDirData pFunc) { ftpRecvDir = pFunc; } void RegiestFileFun(FtpRecvFileData pFunc) { ftpRecvFile = pFunc; } void SetCharSet(FtpCharSet charSet) { m_charSet = charSet; } void SetReturnFlagState(); bool GetReturnFlagState(); int GetSumSpeed(); void SetSumSpeed(int iParam); private: char m_ip[16]; //服务器IP地址 int m_port; //端口 SOCKET m_s; SOCKADDR_IN m_ServerAddr; FtpRecvDirData ftpRecvDir; //接受目录回调 FtpRecvFileData ftpRecvFile; //接受文件回调 FtpCharSet m_charSet; WSADATA m_wsaData; CRITICAL_SECTION m_cs; //临界区变量 int m_iSumSpeed; //实际下载速度 某时间段 public: char m_strError[256]; //错误信息 char m_fileName[256]; //当前下载文件名 int m_Error; //错误码 int m_fileStart; //下载起始位置 int m_fileEnd; //下载截止位置 int m_iFilePos; //当前位置 int m_iCheckPos; //检查位置由外部读取, 确定速度 int m_iMaxRecvSpeed; //限制下载速度(byte) 时间间隔为100ms int m_iRecvSpeed; //实际下载速度(byte) 时间间隔为100ms int m_iDownState; //下载情况 :0.下载进行 1.下载完成 2.下载失败 3.未启动文件下载 bool m_bReturnFlag; //设置返回标志 }; 实现: // // // FtpClient.cpp // 接口调用者需要实现回调函数 // #include "StdAfx.h" #include <stdio.h> #include "FtpClient.h" #include "char_set_util.h" // //FtpClientControl FtpClientControl::FtpClientControl() { popFtpMsg = NULL; m_port = 0; ZeroMemory(m_ip, sizeof(m_ip)); m_Error = WSAStartup(MAKEWORD(2,2), &m_wsaData); if(m_Error != 0) { m_Error = WSAGetLastError(); sprintf(m_strError, "winsock初始化时发生错误。 Error Codes: %d", WSAGetLastError()); return; } m_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_s == INVALID_SOCKET) { sprintf(m_strError, "failed to create socket! Error Codes: %d", WSAGetLastError()); m_Error = WSAGetLastError(); return; } unsigned long ul = 1; int iRet; iRet = ioctlsocket(m_s, FIONBIO, (unsigned long *)&ul); if (iRet == SOCKET_ERROR) { sprintf(m_strError, "failed to ioctlsocket FIONBIO! Error Codes: %d", WSAGetLastError()); m_Error = WSAGetLastError(); return; } m_bReturnFlag = false; //设置返回标志 } FtpClientControl::FtpClientControl(PopFtpMessage pFunc) { popFtpMsg = pFunc; m_port = 0; ZeroMemory(m_ip, sizeof(m_ip)); m_Error = WSAStartup(MAKEWORD(2,2), &m_wsaData); if(m_Error != 0) { sprintf(m_strError, "winsock初始化时发生错误。 Error Codes: %d", WSAGetLastError()); return; } m_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_s == INVALID_SOCKET) { sprintf(m_strError, "failed to create socket! Error Codes: %d", WSAGetLastError()); m_Error = WSAGetLastError(); return; } unsigned long ul = 1; int iRet; iRet = ioctlsocket(m_s, FIONBIO, (unsigned long *)&ul); if (iRet == SOCKET_ERROR) { sprintf(m_strError, "failed to ioctlsocket FIONBIO! Error Codes: %d", WSAGetLastError()); m_Error = WSAGetLastError(); return; } m_bReturnFlag = false; //设置返回标志 } FtpClientControl::~FtpClientControl() { closesocket(m_s); WSACleanup(); } bool FtpClientControl::Init(char* ip, int port) { timeval tv; fd_set fdCnn; strcpy(m_ip, ip); m_port = port; m_ServerAddr.sin_family = AF_INET; m_ServerAddr.sin_port = htons(m_port); m_ServerAddr.sin_addr.s_addr = inet_addr(m_ip); m_Error = 0; tv.tv_sec = 3; //设置3秒 超时 tv.tv_usec = 0; //连接服务器 if (connect(m_s, (SOCKADDR *)&m_ServerAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) { m_Error = WSAGetLastError(); if (m_Error != WSAEWOULDBLOCK) { sprintf(m_strError, "connect error. Error Codes: %d", WSAGetLastError()); closesocket(m_s); return false; } m_Error = 0; } FD_ZERO(&fdCnn); FD_SET(m_s, &fdCnn); switch (select(0, NULL, &fdCnn, NULL, &tv)) { case SOCKET_ERROR: { m_Error = WSAGetLastError(); return false; }; case 0: { m_Error = -2; //time out return false; }; default: { if (FD_ISSET(m_s, &fdCnn)) { ReadRsp(); return true; } else { m_Error = WSAGetLastError(); closesocket(m_s); return false; } }; } return false; } void FtpClientControl::ReadRsp() { int iPos = 0; int iRead = 0; char buff[4096]; fd_set fdread; timeval tv; bool isBreak = false; ZeroMemory(buff, sizeof(buff)); //初始化 ZeroMemory(m_recvData, sizeof(m_recvData)); m_code = 0; m_Error = 0; tv.tv_sec = 3; //设置3秒 超时 tv.tv_usec = 0; FD_ZERO(&fdread); FD_SET(m_s, &fdread); switch(select(0, &fdread, NULL, NULL, &tv)) { case SOCKET_ERROR: { m_Error = WSAGetLastError(); //交由上层程序处理错误 是closesocket 还是重试 break; }; case 0: { m_Error = -2; //time out break; }; default: { if (FD_ISSET(m_s, &fdread)) { do { if (m_bReturnFlag) //返回 等待关闭对象 { m_Error = -3; //设置返回出错信息,3:外部挂起 return; } iRead = recv(m_s, (char*)buff, 4096, 0); if (iRead == SOCKET_ERROR) { m_Error = WSAGetLastError(); if (m_Error != WSAEWOULDBLOCK) { sprintf(m_strError, "read response error. Error Codes: %d", WSAGetLastError()); closesocket(m_s); break; } else { m_Error = -1; //连接关闭 sprintf(m_strError, "connect close"); closesocket(m_s); break; } } memcpy(m_recvData + iPos, buff, iRead); iPos += iRead; ZeroMemory(buff, iRead); for (int i = iPos; i > 0; i--) //从后判断是否到结束 { if (m_recvData[i] == '/r' && m_recvData[i+1] == '/n') { m_recvData[i] = '/0'; isBreak = true; m_Error = 0; break; } } if (isBreak) //接收结束 { break; } FD_CLR(m_s, &fdread); FD_SET(m_s, &fdread); switch(select(0, &fdread, NULL, NULL, &tv)) //回滚,检测是否再有数据读取 { case SOCKET_ERROR: { m_Error = WSAGetLastError(); break; }; case 0: { m_Error = -2; //time out break; }; default: { if (FD_ISSET(m_s, &fdread)) { m_Error = 0; } else { m_Error = WSAGetLastError(); } } } if (m_Error != 0) //出错 退出循环 { break; } } while(iRead > 0); } else { m_Error = WSAGetLastError(); } }; } if (!PrintData(iPos)) { m_Error = -100; //解释错误 } } bool FtpClientControl::PrintData(int iPos) { if (strlen(m_recvData) > 4) //是否包含数据 输出 { char strCode[3]; memcpy(strCode, m_recvData, 3); m_code = atoi(strCode); //抽取命令返回码 memcpy(m_recvData, m_recvData + 4, iPos - 4); //抽取附带信息 m_recvData[iPos - 4] = '/0'; if (popFtpMsg != NULL) { (*popFtpMsg)(m_code, m_recvData); } return true; } else { return false; } } void FtpClientControl::SubmitData(char* submitData) { int iSend = 0; int iSumSend = 0; fd_set fdwrite; timeval tv; int iSize = strlen(submitData); tv.tv_sec = 3; //设置3秒 超时 tv.tv_usec = 0; FD_ZERO(&fdwrite); FD_SET(m_s, &fdwrite); m_Error = 0; while(iSumSend < iSize) { if (m_bReturnFlag) //返回 等待关闭对象 { m_Error = -3; //设置返回出错信息,3:外部挂起 return; } switch (select(0, NULL, &fdwrite, NULL, &tv)) { case SOCKET_ERROR: { m_Error = WSAGetLastError(); return; } case 0: { m_Error = -2; //time out return; } default: { if (FD_ISSET(m_s, &fdwrite)) { iSend = send(m_s, submitData + iSumSend, iSize - iSumSend, 0); //提交数据 if(iSend == SOCKET_ERROR) { m_Error = WSAGetLastError(); sprintf(m_strError, "write command error. Error Codes: %d", WSAGetLastError()); closesocket(m_s); return; } else if (iSend == WSAEWOULDBLOCK) { continue; } iSumSend += iSend; } } } } } int FtpClientControl::Login(char* pUserName, char* pPassword) { bool isSubmit; isSubmit = SubmitCommand(user, pUserName); if (isSubmit) { if (m_code == 331) { isSubmit = SubmitCommand(pass, pPassword); if (isSubmit) { if (m_code == 230) { return 0; } else { return 2; } } else { return -1; } } else { return 1; } } else { return -1; } return 0; } char* FtpClientControl::GetErrorMsg() { return m_strError; } bool FtpClientControl::SubmitCommand(FtpCommand ftpCmd, char* param) { char Command[MAX_PATH]; bool isCommand = false; ZeroMemory(Command, MAX_PATH); switch(ftpCmd) { case abor: strcat(Command, "ABOR"); isCommand = true; break; case allo: strcat(Command, "ALLO"); isCommand = true; break; case appe: strcat(Command, "APPE"); isCommand = true; break; case cudp: strcat(Command, "CUDP"); isCommand = true; break; case list: strcat(Command, "LIST"); isCommand = true; break; case pass: strcat(Command, "PASS"); isCommand = true; break; case port: strcat(Command, "PORT"); isCommand = true; break; case quit: strcat(Command, "QUIT"); isCommand = true; break; case retr: strcat(Command, "RETR"); isCommand = true; break; case stor: strcat(Command, "STOR"); isCommand = true; break; case syst: strcat(Command, "SYST"); isCommand = true; break; case type: strcat(Command, "TYPE"); isCommand = true; break; case user: strcat(Command, "USER"); isCommand = true; break; case pasv: strcat(Command, "PASV"); isCommand = true; break; case cwd: strcat(Command, "CWD"); isCommand = true; break; case size: strcat(Command, "SIZE"); isCommand = true; break; case mkd: strcat(Command, "MKD"); isCommand = true; break; case dele: strcat(Command, "DELE"); isCommand = true; break; case rmd: strcat(Command, "RMD"); isCommand = true; break; case help: strcat(Command, "HELP"); isCommand = true; break; case mode: strcat(Command, "MODE"); isCommand = true; break; case noop: strcat(Command, "NOOP"); isCommand = true; break; case rest: strcat(Command, "REST"); isCommand = true; break; case rnto: strcat(Command, "RNTO"); isCommand = true; break; } if (isCommand) { if (strcmp(param, "") != 0) { strcat(Command, " "); strcat(Command, param); strcat(Command, "/r/n"); } else { strcat(Command, "/r/n"); } this->SubmitData(Command); if (m_Error == 0) { ReadRsp(); return true; } closesocket(m_s); return false; } else { return false; } } inline int FtpClientControl::GetPasvPort(char pasvData[256]) { char *pdest; char sTempDate[256]; int iFPos, iSPos, i, j, k; ZeroMemory(sTempDate, sizeof(sTempDate)); pdest = strchr(pasvData, '(');//返回出现位置指针 iFPos = (int)(pdest - pasvData + 1); pdest = strchr(pasvData, ')');//返回出现位置指针 iSPos = (int)(pdest - pasvData + 1); memcpy(sTempDate, pasvData + iFPos , iSPos - iFPos - 1); int ilength = strlen(sTempDate); char sTemp[5], sTemp2[5]; ZeroMemory(sTemp, sizeof(sTemp)); ZeroMemory(sTemp2, sizeof(sTemp2)); for (i = ilength - 1, j = 0, k = 0; i >0; i--) { if (sTempDate[i] != ',') { if (k ==0) { sTemp[j] = sTempDate[i]; j++; } else { sTemp2[j] = sTempDate[i]; j++; } } else { k++; j = 0; if (k>1) { break; } } } j = strlen(sTemp); //抽取低位 for (i = 0, k = j - 1; i < (j/2); i++) { char cTemp = sTemp[k]; sTemp[k] = sTemp[i]; sTemp[i] = cTemp; } j = strlen(sTemp2); //抽取高位 for (i = 0, k = j - 1; i < (j/2); i++) { char cTemp = sTemp2[k]; sTemp2[k] = sTemp2[i]; sTemp2[i] = cTemp; } unsigned short lport = atoi(sTemp); //PORT 低位 unsigned short uport = atoi(sTemp2); //PORT 高位 uport = uport<<8; int iProt = uport + lport; this->m_pasvPort = iProt; return iProt; } int FtpClientControl::Pasv() { SubmitCommand(pasv, ""); if (m_code == 227) { int iPort = GetPasvPort(m_recvData); return iPort; } else { return 0; } } int FtpClientControl::Size(char *pFileName) { SubmitCommand(size, pFileName); if (m_code == 213) { int iFileSize = atoi(m_recvData); return iFileSize; } else { return 0; } } bool FtpClientControl::Type(char *pType) { SubmitCommand(type, pType); if (m_code == 200) { return true; } else { return false; } } bool FtpClientControl::CWD(char *pPath) { SubmitCommand(cwd, pPath); if (m_code == 250) { return true; } else { return false; } } bool FtpClientControl::Quit() { SubmitCommand(quit, ""); if (m_code == 221) { return true; } else { return false; } } bool FtpClientControl::Dele(char *pFileName) { SubmitCommand(dele, pFileName); if (m_code == 250) { return true; } else { return false; } } bool FtpClientControl::Rmd(char *pDirName) { SubmitCommand(rmd, pDirName); if (m_code == 250) { return true; } else { return false; } } bool FtpClientControl::Mkd(char *pDirName) { SubmitCommand(rmd, pDirName); if (m_code == 257) { return true; } else { return false; } } bool FtpClientControl::Rest(char *pNum) { SubmitCommand(rest, pNum); if (m_code == 350) { return true; } else { return false; } } void FtpClientControl::SetReturnFlagState() { m_bReturnFlag = true; } bool FtpClientControl::GetReturnFlagState() { return m_bReturnFlag; } // //FtpClientData 数据类 /*Entering Passive Mode (172,16,62,72,17,118) 表示32位的IP地址和16位的TCP端口号。 上面的信息以8位为一组,逗号间隔十进制传输。 就是ip为172.16.62.72, port高位为0x11,低位为0x76,即port是 4470 */ FtpClientData::FtpClientData() { ftpRecvDir = NULL; ftpRecvFile = NULL; m_charSet = gb2312; m_fileStart = 0; m_fileEnd = 0; m_iMaxRecvSpeed = 0xffffffff; m_iRecvSpeed = 0; m_iDownState = 3; m_bReturnFlag = false; InitializeCriticalSection(&m_cs); m_Error = WSAStartup(MAKEWORD(2,2), &m_wsaData); if(m_Error != 0) { m_Error = WSAGetLastError(); sprintf(m_strError, "winsock初始化时发生错误。 Error Codes: %d", WSAGetLastError()); return; } SetSumSpeed(0); } bool FtpClientData::InitConnect(char* ip, int port) { m_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (m_s == INVALID_SOCKET) { m_Error = WSAGetLastError(); sprintf(m_strError, "failed to create socket! Error Codes: %d", WSAGetLastError()); return false; } unsigned long ul = 1; int iRet; iRet = ioctlsocket(m_s, FIONBIO, (unsigned long *)&ul); //设置成异步SOCK if (iRet == SOCKET_ERROR) { sprintf(m_strError, "failed to ioctlsocket FIONBIO! Error Codes: %d", WSAGetLastError()); m_Error = WSAGetLastError(); return false; } m_port = port; strcpy(m_ip, ip); m_ServerAddr.sin_family = AF_INET; m_ServerAddr.sin_port = htons(m_port); m_ServerAddr.sin_addr.s_addr = inet_addr(m_ip); if(connect(m_s, (SOCKADDR *)&m_ServerAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) //连接 { m_Error = WSAGetLastError(); if (m_Error != WSAEWOULDBLOCK) { sprintf(m_strError, "connect error. Error Codes: %d", WSAGetLastError()); closesocket(m_s); return false; } m_Error = 0; } timeval tv; fd_set fdCnn; tv.tv_sec = 3; //设置3秒 超时 tv.tv_usec = 0; FD_ZERO(&fdCnn); FD_SET(m_s, &fdCnn); switch (select(0, NULL, &fdCnn, NULL, &tv)) { case SOCKET_ERROR: { m_Error = WSAGetLastError(); return false; }; case 0: { m_Error = -2; //time out return false; }; default: { if (FD_ISSET(m_s, &fdCnn)) { return true; } else { m_Error = WSAGetLastError(); closesocket(m_s); return false; } }; } return false; //退出 出错 } void FtpClientData::RecvDirData() { timeval tv; fd_set fdread; int iPos = 0, iRead = 0 ,iEnd = 0; bool isBreak = false; char buff[4096]; char temp[8192]; char outData[8192]; ZeroMemory(buff, sizeof(buff)); ZeroMemory(temp, sizeof(temp)); ZeroMemory(outData, sizeof(outData)); tv.tv_sec = 3; //设置3秒 超时 tv.tv_usec = 0; FD_ZERO(&fdread); FD_SET(m_s, &fdread); switch(select(0, &fdread, NULL, NULL, &tv)) { case SOCKET_ERROR: { m_Error = WSAGetLastError(); //交由上层程序处理错误 是closesocket 还是重试 break; }; case 0: { m_Error = -2; //time out break; }; default: { if (FD_ISSET(m_s, &fdread)) { do{ if (m_bReturnFlag) //返回 等待关闭对象 { m_Error = -3; //设置返回出错信息,3:外部挂起 return; } iRead = recv(m_s, (char*)buff + iPos, 4096 - iPos, 0); if(iRead < 0) { sprintf(m_strError, "read response error. Error Codes: %d", WSAGetLastError()); closesocket(m_s); break; } else if (iRead == 0) { sprintf(m_strError, "connection closed. Error Codes: %d", WSAGetLastError()); closesocket(m_s); break; } for(int i = 1; i < iRead; i++) { if (buff[i-1] == '/r' && buff[i] == '/n') { iEnd = i; } } memcpy(temp, buff, iEnd + 1); temp[iEnd + 1] = '/0'; if (ftpRecvDir != NULL) { if (m_charSet == utf8) { Utf8ToAscii(temp, outData, strlen(temp)); (*ftpRecvDir)(outData); } else if (m_charSet == gb2312) { (*ftpRecvDir)(temp); } } memmove(buff, buff + iEnd, 4096 - iEnd); ZeroMemory(buff + 4096 - iEnd, iEnd); iPos = 4096 - iEnd; FD_CLR(m_s, &fdread); FD_SET(m_s, &fdread); switch(select(0, &fdread, NULL, NULL, &tv)) //回滚,检测是否再有数据读取 { case SOCKET_ERROR: { m_Error = WSAGetLastError(); isBreak = true; break; }; case 0: { m_Error = -2; //time out isBreak = true; break; }; default: { if (FD_ISSET(m_s, &fdread)) { m_Error = 0; } else { m_Error = WSAGetLastError(); isBreak = true; break; } } } if (isBreak) //接收结束 { break; } } while(iRead > 0); } else { m_Error = WSAGetLastError(); } } } } void FtpClientData::RecvFileDate() { int iRead = 1 ,iEnd = 0, iSum = 0; int iWithOutRecv = 0; byte buff[4096]; DWORD iTime = 0; bool isBreak = false; timeval tv; fd_set fdread; ZeroMemory(buff, sizeof(buff)); iTime = GetTickCount()/100; m_iDownState = 0; //设置下载状态 m_iFilePos = m_fileStart; m_iCheckPos = m_fileStart; tv.tv_sec = 3; //设置3秒 超时 tv.tv_usec = 0; m_Error = 0; FD_ZERO(&fdread); FD_SET(m_s, &fdread); switch(select(0, &fdread, NULL, NULL, &tv)) { case SOCKET_ERROR: { m_Error = WSAGetLastError(); //交由上层程序处理错误 是closesocket 还是重试 break; }; case 0: { m_Error = -2; //time out break; }; default: { if (FD_ISSET(m_s, &fdread)) { do { if (m_bReturnFlag) //返回 等待关闭对象 { m_Error = -3; //设置返回出错信息,3:外部挂起 return; } if (iTime < GetTickCount()/100) //限速 { iTime = GetTickCount()/100; m_iRecvSpeed = 0; } else if (m_iRecvSpeed < m_iMaxRecvSpeed) { if ((m_iRecvSpeed + iRead) < m_iMaxRecvSpeed) { iRead = recv(m_s, (char *)buff, 4096, 0); if (iRead < 0) { sprintf(m_strError, "read response error. Error Codes: %d", WSAGetLastError()); closesocket(m_s); m_iRecvSpeed = 0; m_iDownState = 2; break; } else if (iRead == 0) { sprintf(m_strError, "connection closed. Error Codes: %d", WSAGetLastError()); closesocket(m_s); m_iDownState = 1; m_iRecvSpeed = 0; break; } m_iRecvSpeed += iRead; SetSumSpeed(iRead + m_iSumSpeed); if (ftpRecvFile != NULL) { (*ftpRecvFile)(buff, m_fileStart + iSum, iRead, m_fileName); } iSum += iRead; //收集接收量 m_iFilePos += iRead; //确定位置 ZeroMemory(buff, sizeof(buff)); } if (m_fileStart >= m_fileEnd) { closesocket(m_s); m_iDownState = 1; m_iRecvSpeed = 0; } } FD_CLR(m_s, &fdread); FD_SET(m_s, &fdread); switch(select(0, &fdread, NULL, NULL, &tv)) //回滚,检测是否再有数据读取 { case SOCKET_ERROR: { m_Error = WSAGetLastError(); isBreak = true; break; }; case 0: { m_Error = -2; //time out isBreak = true; break; }; default: { if (FD_ISSET(m_s, &fdread)) { m_Error = 0; } else { m_Error = WSAGetLastError(); isBreak = true; break; } } } if (isBreak) //接收结束 { break; } } while (iRead > 0); } else { m_Error = WSAGetLastError(); } } } } int FtpClientData::CloseConnect() { return closesocket(m_s); } void FtpClientData::SetReturnFlagState() { m_bReturnFlag = true; } bool FtpClientData::GetReturnFlagState() { return m_bReturnFlag; } FtpClientData::~FtpClientData() { if (m_s != INVALID_SOCKET) { closesocket(m_s); } WSACleanup(); DeleteCriticalSection(&m_cs); } int FtpClientData::GetSumSpeed() { int iTemp = 0; EnterCriticalSection(&m_cs); iTemp = m_iSumSpeed; m_iSumSpeed = 0; LeaveCriticalSection(&m_cs); return iTemp; } void FtpClientData::SetSumSpeed(int iParam) { EnterCriticalSection(&m_cs); m_iSumSpeed = iParam; LeaveCriticalSection(&m_cs); }