青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Codejie's C++ Space

Using C++

輪子:FTP接口實現(xiàn)

項目中新增對FTP的支持,需求的變更是開發(fā)過程中不可避免的事情,只是變更的時間越靠近項目末期,就越是災(zāi)難。還好這個需求可以設(shè)計的相對獨立,做到盡量不影響已實現(xiàn)部分。
???? 說的FTP,就想起曾經(jīng)寫的一個FTP接口對象,由于現(xiàn)在FTP的實現(xiàn)庫到處都是,因此在寫好此對象時,被同事稱為:做輪子的人~我的想法是,組裝車和制作車應(yīng)該還是有區(qū)別的~
???? 不扯了,下面是實現(xiàn)的代碼,比較啰嗦~

#ifndef?__FTPOPERAOBJECT_H__
#define?__FTPOPERAOBJECT_H__

#include?
<fstream>
#include?
<string>

#include?
"ace/INET_Addr.h"

#include?
"acex/NB_Tcp_Client.h"
#include?
"acex/NB_Tcp_Server.h"

//OK,?support?both?PORT?and?PASV?mode?NOW.


const?int?REPLY_CODE_541????????????????=????541;
const?int?REPLY_CODE_542????????????????=????542;
const?int?REPLY_CODE_543????????????????=????543;
const?int?REPLY_CODE_544????????????????=????544;
const?int?REPLY_CODE_545????????????????=????545;
const?int?REPLY_CODE_546????????????????=????546;


const?std::string?REPLY_COMMENT_541????=????"(inner)Control?connection?is?break.";
const?std::string?REPLY_COMMENT_542????=????"(inner)Control?connection?is?timeout?for?waiting?for?remote?reply.";
const?std::string?REPLY_COMMENT_543????=????"(inner)Control?connection?gets?a?NULL?reply.";
const?std::string?REPLY_COMMENT_544????=????"(inner)Reply?result?is?empty.";
const?std::string?REPLY_COMMENT_545????=????"(inner)Syntax?error,?reply?unrecognized.";
const?std::string?REPLY_COMMENT_546????=????"(inner)Syntax?error,?reply?is?not?expected.";

class?CFTPDataTcpObject;

class?CFTPCtrlTcpObject
{
public:
????
struct?ResultInfo_t
????{
????????
int?m_iResult;
????????std::
string?m_strInfo;
????};
????
????typedef?std::auto_ptr
<CFTPDataTcpObject>?TDataTcpObjectPtr;
public:
????CFTPCtrlTcpObject(
const?size_t?buf_size?=?64?*?1024,?const?ACE_Time_Value&?connect_timeout?=?ACE_Time_Value(2),?const?ACE_Time_Value&?select_timeout?=?ACE_Time_Value(2));
????
virtual?~CFTPCtrlTcpObject();
public:
????
int?Open(const?ACE_INET_Addr&?stAddr);
????
int?Connect(const?std::string&?strUser,?const?std::string&?strPasswd);
????
int?Close();

????
int?CmdChgDir(const?std::string&?strDir);
????
int?CmdChgLocalDir(const?std::string&?strDir);
????
int?CmdMkDir(const?std::string&?strDir);
????
int?CmdDelFile(const?std::string&?strFile);
????
int?CmdType(bool?bASCII?=?true);
????
int?CmdNoop();
????
int?CmdRenFile(const?std::string&?strOldFile,?const?std::string&?strNewFile);
????
int?CmdGetFile(const?std::string&?strRemoteFile,?const?std::string&?strLocalFile);
????
int?CmdPutFile(const?std::string&?strLocalFile,?const?std::string&?strRemoteFile);
????
int?CmdNLst(const?std::string&?strFilter,?std::string&?strOutput);
????
int?CmdList(const?std::string&?strFilter,?std::string&?strOutput);

????
int?SendCmdWithDataStream(const?std::string&?strCmd,?std::ostream&?os);
????
int?SendCmdWithDataStream(const?std::string&?strCmd,?char*?pchData,?size_t&?szDataRead);
????
????
bool?IsConnected()?const?{?return?_bConnected;?}
????
bool?IsASCII()?const?{?return?_bASCII;?}
????
const?ResultInfo_t&?GetResultInfo()?const;????
????size_t?AffectedSize()?
const;

????
void?PortMode()?{?_bPortMode?=?true;?}
????
void?PasvMode()?{?_bPortMode?=?false;?}
????
void?SetStopFlag(bool?bStop)?{?_bTransStop?=?bStop;?}
public:
????
int?SendCommand(const?std::string&?strCmd);
????
int?RecvResult(ResultInfo_t&?stResult);
????
int?Is200Result(const?ResultInfo_t&?stResult)?const;
????
int?Is100Result(const?ResultInfo_t&?stResult)?const;
????
int?Is300Result(const?ResultInfo_t&?stResult)?const;
????
int?GetLocalAddr(ACE_INET_Addr&?stAddr);
????unsigned?
short?GetRandPort();
????std::
string?AnalyseAddr(const?ACE_INET_Addr&?stAddr)?const;????
????ACE_INET_Addr?AnalyseAddr(
const?std::string&?strAddr)?const;
public:
????
int?RecvResult();
????
int?ResultCode()?const;
????
const?std::string&?ResultInfo()?const;

????
int?Is200Result()?const;
????
int?Is100Result()?const;
????
int?Is300Result()?const;
protected:
????
bool?_bConnected;
????ACE_RANDR_TYPE?_seed;
????
char?_acResultBuf[2048];
????size_t?_szResultSize;
????
bool?_bASCII;
????size_t?_szAffectedSize;
//can?used?after?get?or?put?command.
????bool?_bTransStop;
????
bool?_bPortMode;
private:
????size_t?_szBufSize;
????ACE_Time_Value?_stConnTimeout;
????ACE_Time_Value?_stSelectTimeout;

????std::auto_ptr
<ACEX_TcpStream>?_stTcpStreamPtr;
????ACE_SOCK_Connector?_stConnector;
private:
????ResultInfo_t?_stResultInfo;
};

//
class?CFTPDataTcpObject
{
public:
????
enum?TransStatus?{?TS_UNKNWON?=?-1,?TS_READ?=?0,?TS_WRITE,?TS_TIMEOUT?};
public:
????CFTPDataTcpObject(CFTPCtrlTcpObject
&?ctrlobject,?size_t?buffsize,?const?ACE_Time_Value&?timeout)
????????:?_stCtrlObject(ctrlobject),?_szBuffSize(buffsize),?_stTimeout(timeout)
????????,?_stTcpStreamPtr(NULL)
????????,?_bStop(
false),?_bOpen(false)
????{
????}
????
virtual?~CFTPDataTcpObject();

????
virtual?int?Get(const?std::string&?remote,?const?std::string&?local,?size_t&?size)?=?0;
????
virtual?int?Put(const?std::string&?remote,?const?std::string&?local,?size_t&?size)?=?0;
????
virtual?int?SendCmd(const?std::string&?strCmd,?std::ostream&?os)?=?0;
????
virtual?int?SendCmd(const?std::string&?strCmd,?char*&?pchData,?size_t&?szDataRead)?=?0;
????
void?Stop()?{?_bStop?=?true;?}
????
virtual?void?Close();

protected:
????TransStatus?SelectRead(size_t
&?size);
????TransStatus?SelectWrite();
????
int?Read(char*&?data,?size_t&?size);
????
int?Write(const?char*?data,?size_t?size);
????
int?Read(std::ofstream&?ofile,?size_t&?size);
????
int?Write(std::ifstream&?ifile,?size_t&?size);
????
int?Read(std::ostream&?os,?size_t&?size);
protected:
????CFTPCtrlTcpObject
&?_stCtrlObject;
????size_t?_szBuffSize;
????ACE_Time_Value?_stTimeout;
protected:
????ACE_INET_Addr?_stLocalAddr;
????ACE_INET_Addr?_stRemoteAddr;
????std::auto_ptr
<ACEX_TcpStream>?_stTcpStreamPtr;
protected:
????
bool?_bStop;
????
bool?_bOpen;
};
//
class?CFTPPortDataTcpObject?:?public?CFTPDataTcpObject
{
public:
????CFTPPortDataTcpObject(CFTPCtrlTcpObject
&?ctrlobject,?size_t?buffsize=?64?*?1024,?const?ACE_Time_Value&?timeout?=?ACE_Time_Value(2));
????
virtual?~CFTPPortDataTcpObject();

????
virtual?int?Get(const?std::string&?remote,?const?std::string&?local,?size_t&?size);
????
virtual?int?Put(const?std::string&?remote,?const?std::string&?local,?size_t&?size);
????
virtual?int?SendCmd(const?std::string&?strCmd,?char*&?pchData,?size_t&?szDataRead);
????
virtual?int?SendCmd(const?std::string&?strCmd,?std::ostream&?os);
protected:
????
int?Open();
????
int?Port();
????
int?Accept();
private:
????ACE_SOCK_Acceptor?_stAcceptor;
};
//
class?CFTPPasvDataTcpObject?:?public?CFTPDataTcpObject
{
public:
????CFTPPasvDataTcpObject(CFTPCtrlTcpObject
&?ctrlobject,?size_t?buffsize?=?64?*?1024,?const?ACE_Time_Value&?timeout?=?ACE_Time_Value(2));
????
virtual?~CFTPPasvDataTcpObject();

????
virtual?int?Get(const?std::string&?remote,?const?std::string&?local,?size_t&?size);
????
virtual?int?Put(const?std::string&?remote,?const?std::string&?local,?size_t&?size);
????
virtual?int?SendCmd(const?std::string&?strCmd,?char*&?pchData,?size_t&?szDataRead);
????
virtual?int?SendCmd(const?std::string&?strCmd,?std::ostream&?os);
protected:
????
int?Pasv();
????
int?Connect();
private:
????ACE_SOCK_Connector?_stConnector;
};


#endif


#include?
<stdexcept>
#include?
<sstream>

#include?
"ace/Handle_Set.h"
#include?
"ace/OS_NS_time.h"

#include?
"acex/ACEX.h"

#include?
"FTPOperaObject.h"

CFTPCtrlTcpObject::CFTPCtrlTcpObject(
const?size_t?buf_size,?const?ACE_Time_Value&?connect_timeout,?const?ACE_Time_Value&?select_timeout)
:?_bConnected(
false)
,?_seed(ACE_OS::time(NULL))
,?_szResultSize(
0)
,?_bASCII(
false)
,?_szAffectedSize(
0)
,?_bTransStop(
false)
,?_bPortMode(
true)
,?_szBufSize(buf_size)
,?_stConnTimeout(connect_timeout)
,?_stSelectTimeout(select_timeout)
{
}

CFTPCtrlTcpObject::
~CFTPCtrlTcpObject()
{
????Close();
}

int?CFTPCtrlTcpObject::SendCommand(const?std::string&?strCmd)
{
????
if(!_stTcpStreamPtr->good())
????????
return?-1;
????std::
string?str?=?strCmd?+?"\r\n";
????_stTcpStreamPtr
->write(str.c_str(),?str.size());
????_stTcpStreamPtr
->flush();

????ACEX_LOG_OS(LM_DEBUG,?
"<<CFTPCtrlTcpObject>>SendCommand()?cmd?:"?<<?str?<<?std::endl);

????
return?_stTcpStreamPtr->good()???0?:?-1;
}

int?CFTPCtrlTcpObject::RecvResult(ResultInfo_t&?stResult)
{
????
if(!_stTcpStreamPtr->good())
????{
????????stResult.m_iResult?
=?REPLY_CODE_541;
????????stResult.m_strInfo?
=?REPLY_COMMENT_541;
????????
return?-1;
????}

????ACE_Handle_Set?rd_set;
????rd_set.reset();
????rd_set.set_bit(_stTcpStreamPtr
->get_handle());
????
int?iMaxFd?=?0;
#if?!defined(_WIN32)
????iMaxFd?
=?_stTcpStreamPtr->get_handle()?+?1;
#endif
????
if(ACE::select(iMaxFd,?&rd_set,?NULL,?NULL,?&_stSelectTimeout)?<=?0)
????{
//timeout
????????stResult.m_iResult?=?REPLY_CODE_542;
????????stResult.m_strInfo?
=?REPLY_COMMENT_542;
????????
return?-1;
????}
????_stTcpStreamPtr
->under_flow();
????
if(!_stTcpStreamPtr->good())
????{
????????stResult.m_iResult?
=?REPLY_CODE_541;
????????stResult.m_strInfo?
=?REPLY_COMMENT_541;
????????
return?-1;
????}
????size_t?szRead?
=?_stTcpStreamPtr->in_avail();
????
if(szRead?<=?0)
????{
????????stResult.m_iResult?
=?REPLY_CODE_543;
????????stResult.m_strInfo?
=?REPLY_COMMENT_543;
????????
return?-1;
????}
????
while(szRead?>?0)
????{
????????_stTcpStreamPtr
->read(_acResultBuf?+?_szResultSize,?szRead);
????????_szResultSize?
+=?szRead;
????????szRead?
=?_stTcpStreamPtr->in_avail();
????}
????std::
string?strInfo;
????strInfo.assign(_acResultBuf,?_szResultSize);

????stResult.m_strInfo?
=?"";
????
try
????{
????????std::
string::size_type?szPos?=?strInfo.find_first_of("\r\n");
????????
while(szPos?!=?std::string::npos)
????????{
????????????stResult.m_strInfo?
=?strInfo.substr(0,?szPos);
????????????strInfo?
=?strInfo.substr(szPos?+?2);
????????????szPos?
=?strInfo.find_first_of("\r\n");
????????}

????????
if(stResult.m_strInfo.empty())
????????{
????????????stResult.m_iResult?
=?REPLY_CODE_544;
????????????stResult.m_strInfo?
=?REPLY_COMMENT_544;
????????????
return?-1;
????????}
????????szPos?
=?stResult.m_strInfo.find_first_of("?");
????????
if(szPos?==?std::string::npos)
????????{
????????????stResult.m_iResult?
=?REPLY_CODE_545;
????????????stResult.m_strInfo?
=?REPLY_COMMENT_545;
????????????
return?-1;
????????}
????????stResult.m_iResult?
=?atoi(stResult.m_strInfo.substr(0,?szPos).c_str());
????????stResult.m_strInfo?
=?stResult.m_strInfo.substr(szPos?+?1);
????}
????
catch(std::out_of_range&?e)
????{
????????ACEX_LOG_OS(LM_WARNING,?
"<<CFTPCtrlTcpObject>>RecvResult()?exception(out_of_range)?-?remote?maybe?not?FTP?server."?<<?std::endl);
????????stResult.m_iResult?
=?REPLY_CODE_546;
????????stResult.m_strInfo?
=?REPLY_COMMENT_546;
????????
return?-1;
????}

????_szResultSize?
=?0;

????
return?0;
}

int?CFTPCtrlTcpObject::RecvResult()
{
????
if(RecvResult(_stResultInfo)?==?0)
????{
????????ACEX_LOG_OS(LM_DEBUG,?
"<<CFTPCtrlTcpObject>>RecvResult()?Result("?<<?_stResultInfo.m_iResult?<<?")"?<<?_stResultInfo.m_strInfo?<<?std::endl);

????????
return?0;
????}
????
else
????{
????????ACEX_LOG_OS(LM_WARNING,?
"<<CFTPCtrlTcpObject>>RecvResult()?Result("?<<?_stResultInfo.m_iResult?<<?")"?<<?_stResultInfo.m_strInfo?<<?std::endl);
????????
return?-1;
????}
}

int?CFTPCtrlTcpObject::ResultCode()?const
{
????
return?_stResultInfo.m_iResult;
}

const?std::string&?CFTPCtrlTcpObject::ResultInfo()?const
{
????
return?_stResultInfo.m_strInfo;
}

int?CFTPCtrlTcpObject::Open(const?ACE_INET_Addr&?stAddr)
{
????_stTcpStreamPtr.reset(
new?ACEX_TcpStream(_szBufSize));
????ACE_Time_Value?st(
5,0);
????
if(_stConnector.connect(*_stTcpStreamPtr.get(),?stAddr,?&st)?==?0)
????{
????????_stTcpStreamPtr
->block(0);
????????RecvResult();
????????
if(Is200Result()?==?0)
????????{
????????????_bConnected?
=?true;
????????????
return?0;
????????}
????????
else
????????{
????????????Close();
????????}
????}
????
return?-1;
}

int?CFTPCtrlTcpObject::Connect(const?std::string&?strUser,?const?std::string&?strPasswd)
{
????
//if(_bConnected)
????
//{
????
//????SendCommand("USER?"?+?strUser);
????
//????RecvResult();
????
//????if(_stResultInfo.m_iResult?==?331)
????
//????{
????
//????????SendCommand("PASS?"?+?strPasswd);
????
//????????RecvResult();
????
//????????if(Is200Result()?==?0)
????
//????????{//set?default?trans?mode
????
//????????????return?CmdType(_bASCII);
????
//????????}
????
//????}
????
//}

????
//return?-1;

????
if(_bConnected)
????{
????????SendCommand(
"USER?"?+?strUser);
????????
while(RecvResult()?==?0)
????????{
????????????
if(_stResultInfo.m_iResult?==?331)
????????????{
????????????????SendCommand(
"PASS?"?+?strPasswd);
????????????????RecvResult();
????????????????
if(Is200Result()?==?0)
????????????????{
//set?default?trans?mode
????????????????????return?CmdType(_bASCII);
????????????????}
????????????}
????????}
????}

????
return?-1;
}

int?CFTPCtrlTcpObject::Close()
{
????
if(_bConnected)
????{
????????SendCommand(
"QUIT");
????????RecvResult();
????????_stTcpStreamPtr
->close();
????????_bConnected?
=?false;
????}
????
return?0;
}

const?CFTPCtrlTcpObject::ResultInfo_t&?CFTPCtrlTcpObject::GetResultInfo()?const
{
????
return?_stResultInfo;
}

int?CFTPCtrlTcpObject::Is200Result(const?ResultInfo_t&?stResult)?const
{
????
if(stResult.m_iResult?>=200?&&?stResult.m_iResult?<?300)
????????
return?0;
????
else
????????
return?-1;
}

int?CFTPCtrlTcpObject::Is100Result(const?ResultInfo_t&?stResult)?const
{
????
if(stResult.m_iResult?>=100?&&?stResult.m_iResult?<?200)
????????
return?0;
????
else
????????
return?-1;
}

int?CFTPCtrlTcpObject::Is300Result(const?ResultInfo_t&?stResult)?const
{
????
if(stResult.m_iResult?>=300?&&?stResult.m_iResult?<?400)
????????
return?0;
????
else
????????
return?-1;
}

int?CFTPCtrlTcpObject::Is200Result()?const
{
????
return?Is200Result(_stResultInfo);
}

int?CFTPCtrlTcpObject::Is100Result()?const
{
????
return?Is100Result(_stResultInfo);
}

int?CFTPCtrlTcpObject::Is300Result()?const
{
????
return?Is300Result(_stResultInfo);
}

//////////////////////////////////////////////////////////////////////////

int?CFTPCtrlTcpObject::CmdChgDir(const?std::string&?strDir)
{
????SendCommand(
"CWD?"?+?strDir);
????RecvResult();
????
return?Is200Result();
}

int?CFTPCtrlTcpObject::CmdChgLocalDir(const?std::string&?strDir)
{
????
return?ACE_OS::chdir(strDir.c_str());
}

int?CFTPCtrlTcpObject::CmdMkDir(const?std::string&?strDir)
{
????SendCommand(
"MKD?"?+?strDir);
????RecvResult();
????
return?Is200Result();
}

int?CFTPCtrlTcpObject::CmdDelFile(const?std::string&?strFile)
{
????SendCommand(
"DELE?"?+?strFile);
????RecvResult();
????
return?Is200Result();
}

int?CFTPCtrlTcpObject::CmdType(bool?bASCII?/*?=?true?*/)
{
????_bASCII?
=?bASCII;
????
if(bASCII)
????{
????????SendCommand(
"TYPE?A");
????}
????
else
????{
????????SendCommand(
"TYPE?I");
????}
????RecvResult();
????
return?Is200Result();
}

int?CFTPCtrlTcpObject::CmdNoop()
{
????SendCommand(
"NOOP");
????RecvResult();
????
return?Is200Result();
}

int?CFTPCtrlTcpObject::CmdRenFile(const?std::string&?strOldFile,?const?std::string&?strNewFile)
{
????SendCommand(
"RNFR?"?+?strOldFile);
????RecvResult();
????
if(_stResultInfo.m_iResult?==?350)
????{
????????SendCommand(
"RNTO?"?+?strNewFile);
????????RecvResult();
????????
return?Is200Result();
????}
????
else
????{
????????
return??-1;
????}
}

int?CFTPCtrlTcpObject::CmdGetFile(const?std::string&?strRemoteFile,?const?std::string&?strLocalFile)
{
????_szAffectedSize?
=?0;

????TDataTcpObjectPtr?ptr(NULL);
????
if(_bPortMode)
????????ptr.reset(
new?CFTPPortDataTcpObject(*this));
????
else
????????ptr.reset(
new?CFTPPasvDataTcpObject(*this));

????
if(ptr->Get(strRemoteFile,?strLocalFile,?_szAffectedSize)?!=?0)
????????
return?-1;

????ptr
->Close();

????RecvResult();
????
return?Is200Result();
}

int?CFTPCtrlTcpObject::CmdPutFile(const?std::string&?strLocalFile,?const?std::string&?strRemoteFile)
{
????_szAffectedSize?
=?0;

????TDataTcpObjectPtr?ptr(NULL);
????
if(_bPortMode)
????????ptr.reset(
new?CFTPPortDataTcpObject(*this));
????
else
????????ptr.reset(
new?CFTPPasvDataTcpObject(*this));

????
if(ptr->Put(strRemoteFile,?strLocalFile,?_szAffectedSize)?!=?0)
????????
return?-1;

????ptr
->Close();

????RecvResult();
????
return?Is200Result();????
}

int?CFTPCtrlTcpObject::CmdNLst(const?std::string&?strFilter,?std::string&?strOutput)
{
????std::
string?strCmd?=?"NLST";
????
if(!strFilter.empty())
????????strCmd?
+=?"?"?+?strFilter;
????std::ostringstream?ostr;
????
if(SendCmdWithDataStream(strCmd,?ostr)?!=?0)
????????
return?-1;
????strOutput?
=?ostr.str();
????
return?0;
}

int?CFTPCtrlTcpObject::CmdList(const?std::string&?strFilter,?std::string&?strOutput)
{
????std::
string?strCmd?=?"LIST";
????
if(!strFilter.empty())
????????strCmd?
+=?"?"?+?strFilter;
????std::ostringstream?ostr;
????
if(SendCmdWithDataStream(strCmd,?ostr)?!=?0)
????????
return?-1;
????strOutput?
=?ostr.str();
????
return?0;
}

int?CFTPCtrlTcpObject::SendCmdWithDataStream(const?std::string&?strCmd,?std::ostream&?os)
{
????TDataTcpObjectPtr?ptr(NULL);
????
if(_bPortMode)
????????ptr.reset(
new?CFTPPortDataTcpObject(*this));
????
else
????????ptr.reset(
new?CFTPPasvDataTcpObject(*this));

????
if(ptr->SendCmd(strCmd,?os)?!=?0)
????????
return?-1;

????ptr
->Close();

????RecvResult();
????
return?Is200Result();????
}

int?CFTPCtrlTcpObject::SendCmdWithDataStream(const?std::string&?strCmd,?char*?pchData,?size_t&?szDataRead)
{
????TDataTcpObjectPtr?ptr(NULL);
????
if(_bPortMode)
????????ptr.reset(
new?CFTPPortDataTcpObject(*this));
????
else
????????ptr.reset(
new?CFTPPasvDataTcpObject(*this));

????
if(ptr->SendCmd(strCmd,?pchData,?szDataRead)?!=?0)
????????
return?-1;

????ptr
->Close();

????RecvResult();
????
return?Is200Result();????
}

size_t?CFTPCtrlTcpObject::AffectedSize()?
const
{
????
return?_szAffectedSize;
}

int?CFTPCtrlTcpObject::GetLocalAddr(ACE_INET_Addr&?stAddr)
{
????
if(!_bConnected)
????????
return?-1;

????_stTcpStreamPtr
->get_local_addr(stAddr);
????
return?0;
}

unsigned?
short?CFTPCtrlTcpObject::GetRandPort()
{
????
int?iRand?=?ACE_OS::rand_r(_seed);
????
while(iRand?<?20000)
????{
????????iRand?
=?ACE_OS::rand_r(_seed);
????}
????
return?iRand;
}

std::
string?CFTPCtrlTcpObject::AnalyseAddr(const?ACE_INET_Addr&?stAddr)?const
{
????std::ostringstream?ostr;
????ostr?
<<?stAddr.get_host_addr();
????ostr?
<<?","?<<?stAddr.get_port_number()?/?256?<<?","?<<?stAddr.get_port_number()?%?256;

????std::
string?str?=?ostr.str();
????std::
string::size_type?st?=?str.find_first_of(".");
????
while(st?!=?std::string::npos)
????{
????????str?
=?str.replace(st,?1,?",");
????????st?
=?str.find_first_of(".");
????}
????
return?str;
}

ACE_INET_Addr?CFTPCtrlTcpObject::AnalyseAddr(
const?std::string&?strAddr)?const
{
????std::
string?str?=?strAddr;
????std::ostringstream?ostr;
????std::
string::size_type?pos?=?str.find(',');
????
if(pos?!=?std::string::npos)
????????ostr?
<<?str.substr(0,?pos)?<<?".";
????
else
????????
return?ACE_INET_Addr("0.0.0.0:0");
????str?
=?str.substr(pos?+?1);

????pos?
=?str.find(',');
????
if(pos?!=?std::string::npos)
????????ostr?
<<?str.substr(0,?pos)?<<?".";
????
else
????????
return?ACE_INET_Addr("0.0.0.0:0");
????str?
=?str.substr(pos?+?1);

????pos?
=?str.find(',');
????
if(pos?!=?std::string::npos)
????????ostr?
<<?str.substr(0,?pos)?<<?".";
????
else
????????
return?ACE_INET_Addr("0.0.0.0:0");
????str?
=?str.substr(pos?+?1);

????pos?
=?str.find(',');
????
if(pos?!=?std::string::npos)
????????ostr?
<<?str.substr(0,?pos)?<<?":";
????
else
????????
return?ACE_INET_Addr("0.0.0.0:0");
????str?
=?str.substr(pos?+?1);

????pos?
=?str.find(',');
????
if(pos?!=?std::string::npos)
????????ostr?
<<?atoi(str.substr(0,?pos).c_str())?*?256?+?atoi(str.substr(pos?+?1).c_str());

????
return?ACE_INET_Addr(ostr.str().c_str());
}

//////////////////////////////////////////////////////////////////////////
CFTPDataTcpObject::~CFTPDataTcpObject()
{
????Close();
}

CFTPDataTcpObject::TransStatus?CFTPDataTcpObject::SelectRead(size_t?
&size)
{
????
if(!_stTcpStreamPtr->good())
????????
return?TS_UNKNWON;

????ACE_Handle_Set?rd_set;
????rd_set.reset();
????rd_set.set_bit(_stTcpStreamPtr
->get_handle());
????
int?iMaxFd?=?0;
#if?!defined(_WIN32)
????iMaxFd?
=?_stTcpStreamPtr->get_handle()?+?1;
#endif
????
if(ACE::select(iMaxFd,?&rd_set,?NULL,?NULL,?&_stTimeout)?<=?0)
????{
????????
return?TS_TIMEOUT;
????}

????_stTcpStreamPtr
->under_flow();
????size?
=?_stTcpStreamPtr->in_avail();

????
return?TS_READ;
}

CFTPDataTcpObject::TransStatus?CFTPDataTcpObject::SelectWrite()
{
????
if(!_stTcpStreamPtr->good())
????????
return?TS_UNKNWON;

????ACE_Handle_Set?wr_set;
????wr_set.reset();
????wr_set.set_bit(_stTcpStreamPtr
->get_handle());
????
int?iMaxFd?=?0;
#if?!defined(_WIN32)
????iMaxFd?
=?_stTcpStreamPtr->get_handle()?+?1;
#endif
????
if(ACE::select(iMaxFd,?NULL,?&wr_set,?NULL,?&_stTimeout)?<=?0)
????{
????????
return?TS_TIMEOUT;
????}
????
return?TS_WRITE;
}

int?CFTPDataTcpObject::Read(char*&?data,?size_t&?size)
{
????size?
=?0;
????data?
=?NULL;

????
while(_stTcpStreamPtr->good())
????{
????????
if(_bStop)
????????????
return?-1;

????????size_t?szRead?
=?0;
????????TransStatus?eTrans?
=?SelectRead(szRead);
????????
if(eTrans?==?TS_READ)
????????{
????????????
if(szRead?==?0)
????????????????
break;
????????????
char*?pch?=?new?char[szRead];
????????????
if(_stTcpStreamPtr->read(pch,?szRead).good())
????????????{
????????????????
if(data?!=?NULL)
????????????????{
????????????????????delete?[]?data;
????????????????????data?
=?new?char[size?+?szRead];
????????????????}
????????????????memcpy(data?
+?size,?pch,?szRead);
????????????????size?
+=?szRead;
????????????}
????????????
else
????????????{
????????????????delete?[]?pch;
????????????????
return?-1;
????????????}
????????????delete?[]?pch;
????????}
????????
else?if(eTrans?==?CFTPDataTcpObject::TS_TIMEOUT)
????????{
????????????
continue;
????????}
????????
else
????????{
????????????
return?-1;
????????}
????}

????
return?0;
}

int?CFTPDataTcpObject::Write(const?char*?data,?size_t?size)
{
????size_t?szWrite?
=?0;

????
while(szWrite?<?size)
????{
????????
if(_bStop)
????????????
return?-1;

????????TransStatus?eTrans?
=?SelectWrite();
????????
if(eTrans?==?CFTPDataTcpObject::TS_WRITE)
????????{
????????????
if(size?-?szWrite?>=?5120)
????????????{
????????????????_stTcpStreamPtr
->write(data?+?szWrite,?5120);
????????????????
if(!_stTcpStreamPtr->flush().good())
????????????????????
return?-1;
????????????}
????????????
else
????????????{
????????????????_stTcpStreamPtr
->write(data?+?szWrite,?size?-?szWrite);
????????????????
if(!_stTcpStreamPtr->flush().good())
????????????????????
return?-1;
????????????}
????????????szWrite?
+=?5120;
????????}
????????
else?if(eTrans?==?CFTPDataTcpObject::TS_TIMEOUT)
????????{
????????????
continue;
????????}
????????
else
????????{
????????????
break;
????????}
????}

????
return?0;
}

int?CFTPDataTcpObject::Read(std::ofstream?&ofile,?size_t&?size)
{
????
if(!ofile.good())
????????
return?-1;

????size?
=?0;

????
while(_stTcpStreamPtr->good())
????{
????????
if(_bStop)
????????????
return?-1;

????????size_t?szRead?
=?0;
????????TransStatus?eTrans?
=?SelectRead(szRead);
????????
if(eTrans?==?TS_READ)
????????{
????????????
if(szRead?==?0)
????????????????
break;
????????????
char*?pch?=?new?char[szRead];
????????????
if(_stTcpStreamPtr->read(pch,?szRead).good())
????????????{
????????????????ofile.write(pch,?szRead);
????????????????size?
+=?szRead;
????????????????
if(!ofile.good())
????????????????{
????????????????????delete?[]?pch;
????????????????????
return?-1;
????????????????}
????????????}
????????????
else
????????????{
????????????????delete?[]?pch;
????????????????
return?-1;
????????????}
????????????delete?[]?pch;
????????}
????????
else?if(eTrans?==?CFTPDataTcpObject::TS_TIMEOUT)
????????{
????????????
continue;
????????}
????????
else
????????{
????????????
return?-1;
????????}
????}

????
return?0;
}

int?CFTPDataTcpObject::Write(std::ifstream?&ifile,?size_t?&size)
{
????
if(!ifile.good())
????????
return?-1;
????size?
=?0;

????
char?buf[5120];
????
while(!ifile.eof()?&&?ifile.good())
????{
????????
if(_bStop)
????????????
return?-1;

????????TransStatus?eTrans?
=?SelectWrite();
????????
if(eTrans?==?CFTPDataTcpObject::TS_WRITE)
????????{????
????????????size_t?szRead?
=?ifile.read(buf,?5120).gcount();
????????????
if(szRead?>?0)
????????????{
????????????????_stTcpStreamPtr
->write(buf,?szRead);
????????????????
if(!_stTcpStreamPtr->flush().good())
????????????????????
return?-1;
????????????????size?
+=?szRead;
????????????}
????????????
else
????????????{
????????????????
break;
????????????}
????????}
????????
else?if(eTrans?==?CFTPDataTcpObject::TS_TIMEOUT)
????????{
????????????
continue;
????????}
????????
else
????????{
????????????
break;
????????}
????}
????
return?0;
}


int?CFTPDataTcpObject::Read(std::ostream?&os,?size_t&?size)
{
????
if(!os.good())
????????
return?-1;

????size?
=?0;

????
while(_stTcpStreamPtr->good())
????{
????????
if(_bStop)
????????????
return?-1;

????????size_t?szRead?
=?0;
????????TransStatus?eTrans?
=?SelectRead(szRead);
????????
if(eTrans?==?TS_READ)
????????{
????????????
if(szRead?==?0)
????????????????
break;
????????????
char*?pch?=?new?char[szRead];
????????????
if(_stTcpStreamPtr->read(pch,?szRead).good())
????????????{
????????????????os.write(pch,?szRead);
????????????????size?
+=?szRead;
????????????????
if(!os.good())
????????????????{
????????????????????delete?[]?pch;
????????????????????
return?-1;
????????????????}
????????????}
????????????
else
????????????{
????????????????delete?[]?pch;
????????????????
return?-1;
????????????}
????????????delete?[]?pch;
????????}
????????
else?if(eTrans?==?CFTPDataTcpObject::TS_TIMEOUT)
????????{
????????????
continue;
????????}
????????
else
????????{
????????????
return?-1;
????????}
????}

????
return?0;
}

void?CFTPDataTcpObject::Close()
{
????
if(_stTcpStreamPtr.get()?!=?NULL)
????{
????????_stTcpStreamPtr
->close();
????????_stTcpStreamPtr.reset(NULL);
????}????
}

////
CFTPPortDataTcpObject::CFTPPortDataTcpObject(CFTPCtrlTcpObject?&ctrlobject,?size_t?buffsize,?const?ACE_Time_Value?&timeout)
:?CFTPDataTcpObject(ctrlobject,?buffsize,?timeout)
{
}

CFTPPortDataTcpObject::
~CFTPPortDataTcpObject()
{
}

int?CFTPPortDataTcpObject::Get(const?std::string?&remote,?const?std::string?&local,?size_t&?size)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????std::ios_base::openmode?mode?
=?std::ios::trunc?|?std::ios::out;
????
if(!_stCtrlObject.IsASCII())
????????mode?
|=?std::ios_base::binary;

????std::ofstream?ofile(local.c_str(),?mode);

????
if(!ofile.is_open()?||?!ofile.good())
????????
return?-1;

????
if(Open()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Get>open()?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Port()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Get>port()?failed."?<<?std::endl);
????????
return?-1;
????}

//????CFTPCtrlTcpObject::ResultInfo_t?result;
????_stCtrlObject.SendCommand("RETR?"?+?remote);
????_stCtrlObject.RecvResult();
????
if(_stCtrlObject.Is100Result()?!=?0)
//????if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Get>RETR?command?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Accept()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Get>accept()?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Read(ofile,?size)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Get>Read()?failed."?<<?std::endl);
????????
return?-1;
????}

????ofile.close();

????
return?0;
}

int?CFTPPortDataTcpObject::Put(const?std::string&?remote,?const?std::string&?local,?size_t&?size)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????std::ios_base::openmode?mode?
=?std::ios_base::in;
????
if(!_stCtrlObject.IsASCII())
????????mode?
|=?std::ios_base::binary;

????std::ifstream?ifile(local.c_str(),?mode);
????
if(!ifile.is_open()?||?!ifile.good())
????????
return?-1;

????
if(Open()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Put>open()?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Port()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Put>port()?failed."?<<?std::endl);
????????
return?-1;
????}
//????CFTPCtrlTcpObject::ResultInfo_t?result;

????_stCtrlObject.SendCommand(
"STOR?"?+?remote);
????_stCtrlObject.RecvResult();
//????if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????if(_stCtrlObject.Is100Result()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Put>STOR?command?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Accept()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Put>accept()?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Write(ifile,?size)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::Put>Write()?failed."?<<?std::endl);
????????
return?-1;
????}

????ifile.close();

????
return?0;
}

int?CFTPPortDataTcpObject::SendCmd(const?std::string&?strCmd,?char*&?pchData,?size_t&?szDataRead)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????
if(Open()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>open()?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Port()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>port()?failed."?<<?std::endl);
????????
return?-1;
????}

//????CFTPCtrlTcpObject::ResultInfo_t?result;
????_stCtrlObject.SendCommand(strCmd);
????_stCtrlObject.RecvResult();
//????if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????if(_stCtrlObject.Is100Result()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>"?<<?strCmd?<<?"?command?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Accept()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>accept()?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Read(pchData,?szDataRead)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>Read()?failed."?<<?std::endl);
????????
return?-1;
????}

????
return?0;
}

int?CFTPPortDataTcpObject::SendCmd(const?std::string&?strCmd,?std::ostream&?os)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????
if(Open()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>open()?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Port()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>port()?failed."?<<?std::endl);
????????
return?-1;
????}

//????CFTPCtrlTcpObject::ResultInfo_t?result;
????_stCtrlObject.SendCommand(strCmd);
????_stCtrlObject.RecvResult();
????
//if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????if(_stCtrlObject.Is100Result()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>"?<<?strCmd?<<?"?command?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Accept()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>accept()?failed."?<<?std::endl);
????????
return?-1;
????}

????size_t?szDataRead?
=?0;
????
if(Read(os,?szDataRead)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPortDataTcpObject::SendCmd>Read()?failed."?<<?std::endl);
????????
return?-1;
????}

????
return?0;
}

int?CFTPPortDataTcpObject::Open()
{
????_stCtrlObject.GetLocalAddr(_stLocalAddr);
????_stLocalAddr.set_port_number(_stCtrlObject.GetRandPort());

????
while(_stAcceptor.open(_stLocalAddr)?!=?0)
????{
????????_stLocalAddr.set_port_number(_stCtrlObject.GetRandPort());
????}

????_bOpen?
=?true;

????
return?0;
}

int?CFTPPortDataTcpObject::Port()
{
//????CFTPCtrlTcpObject::ResultInfo_t?result;

????std::
string?strPort?=?_stCtrlObject.AnalyseAddr(_stLocalAddr);
????_stCtrlObject.SendCommand(
"PORT?"?+?strPort);
????_stCtrlObject.RecvResult();
????
if(_stCtrlObject.Is200Result()?!=?0)
????????
return?-1;

????
return?0;????
}

int?CFTPPortDataTcpObject::Accept()
{
????ACE_Handle_Set?rd_set;
????rd_set.reset();
????rd_set.set_bit(_stAcceptor.get_handle());
????
int?iMaxFd?=?0;
#if?!defined(_WIN32)
????iMaxFd?
=?_stAcceptor.get_handle()?+?1;
#endif
????
if(ACE::select(iMaxFd,?&rd_set,?NULL,?NULL,?&_stTimeout)?>?0)
????{
????????
if(rd_set.is_set(_stAcceptor.get_handle()))
????????{
????????????_stTcpStreamPtr.reset(
new?ACEX_TcpStream(_szBuffSize));
????????????
if(_stAcceptor.accept(*_stTcpStreamPtr.get())?==?0)
????????????{
????????????????_stTcpStreamPtr
->block(0);
????????????}
????????????
else
????????????{
????????????????_stTcpStreamPtr.reset(NULL);
????????????}
????????}
????}
????_stAcceptor.close();

????
if(_stTcpStreamPtr.get()?!=?NULL)
????????
return?0;
????_bOpen?
=?false;
????
return?-1;
}

//
CFTPPasvDataTcpObject::CFTPPasvDataTcpObject(CFTPCtrlTcpObject&?ctrlobject,?size_t?buffsize?/*?=?64?*?1024?*/,?const?ACE_Time_Value&?timeout?/*?=?ACE_Time_Value?*/)
:?CFTPDataTcpObject(ctrlobject,?buffsize,?timeout)
{
}

CFTPPasvDataTcpObject::
~CFTPPasvDataTcpObject()
{
}

int?CFTPPasvDataTcpObject::Get(const?std::string?&remote,?const?std::string?&local,?size_t?&size)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????std::ios_base::openmode?mode?
=?std::ios::trunc?|?std::ios::out;
????
if(!_stCtrlObject.IsASCII())
????????mode?
|=?std::ios_base::binary;

????std::ofstream?ofile(local.c_str(),?mode);

????
if(!ofile.is_open()?||?!ofile.good())
????????
return?-1;

????
if(Pasv()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Get>Pasv()?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Connect()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Get>Connect()?failed."?<<?std::endl);
????????
return?-1;
????}

//????CFTPCtrlTcpObject::ResultInfo_t?result;
????_stCtrlObject.SendCommand("RETR?"?+?remote);
????_stCtrlObject.RecvResult();
//????if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????if(_stCtrlObject.Is100Result()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Get>RETR?command?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Read(ofile,?size)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Get>Read()?failed."?<<?std::endl);
????????
return?-1;
????}

????ofile.close();

????
return?0;
}

int?CFTPPasvDataTcpObject::Put(const?std::string&?remote,?const?std::string&?local,?size_t&?size)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????std::ios_base::openmode?mode?
=?std::ios_base::in;
????
if(!_stCtrlObject.IsASCII())
????????mode?
|=?std::ios_base::binary;

????std::ifstream?ifile(local.c_str(),?mode);
????
if(!ifile.is_open()?||?!ifile.good())
????????
return?-1;

????
if(Pasv()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Put>Pasv()?failed."?<<?std::endl);
????????
return?-1;
????}
????
if(Connect()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Put>Connect()?failed."?<<?std::endl);
????????
return?-1;
????}

//????CFTPCtrlTcpObject::ResultInfo_t?result;
????_stCtrlObject.SendCommand("STOR?"?+?remote);
????_stCtrlObject.RecvResult();
//????if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????if(_stCtrlObject.Is100Result()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Put>STOR?command?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Write(ifile,?size)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::Put>Write()?failed."?<<?std::endl);
????????
return?-1;
????}

????ifile.close();

????
return?0;
}

int?CFTPPasvDataTcpObject::SendCmd(const?std::string&?strCmd,?char*&?pchData,?size_t&?szDataRead)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????
if(Pasv()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>Pasv()?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Connect()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>Connect()?failed."?<<?std::endl);
????????
return?-1;
????}

//????CFTPCtrlTcpObject::ResultInfo_t?result;
????_stCtrlObject.SendCommand(strCmd);
????_stCtrlObject.RecvResult();
//????if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????if(_stCtrlObject.Is100Result()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>"?<<?strCmd?<<?"?command?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Read(pchData,?szDataRead)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>Read()?failed."?<<?std::endl);
????????
return?-1;
????}

????
return?0;
}

int?CFTPPasvDataTcpObject::SendCmd(const?std::string&?strCmd,?std::ostream&?os)
{
????
if(!_stCtrlObject.IsConnected())
????????
return?-1;

????
if(Pasv()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>Pasv()?failed."?<<?std::endl);
????????
return?-1;
????}

????
if(Connect()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>Connect()?failed."?<<?std::endl);
????????
return?-1;
????}

//????CFTPCtrlTcpObject::ResultInfo_t?result;
????_stCtrlObject.SendCommand(strCmd);
????_stCtrlObject.RecvResult();
//????if(result.m_iResult?<?100?||?result.m_iResult?>?199)
????if(_stCtrlObject.Is100Result()?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>"?<<?strCmd?<<?"?command?failed."?<<?std::endl);
????????
return?-1;
????}

????size_t?szDataRead?
=?0;
????
if(Read(os,?szDataRead)?!=?0)
????{
????????ACEX_LOG_OS(LM_ERROR,?
"<CFTPPasvDataTcpObject::SendCmd>Read()?failed."?<<?std::endl);
????????
return?-1;
????}

????
return?0;
}

int?CFTPPasvDataTcpObject::Pasv()
{
//????CFTPCtrlTcpObject::ResultInfo_t?result;

????_stCtrlObject.SendCommand(
"PASV");
????_stCtrlObject.RecvResult();
????
if(_stCtrlObject.ResultCode()?!=?227)
????{
????????
return?-1;
????}
????std::
string?info?=?_stCtrlObject.ResultInfo();
????std::
string?str?=?"";
//????unsigned?short?port?=?0;?
//????size_t?pos?=?0;
????for(std::string::const_iterator?it?=?info.begin();?it?!=?info.end();?++?it)
????{
????????
if((*it?>=?'0'?&&?*it?<=?'9')?||?(*it?==?','))
????????{
????????????str?
+=?*it;
????????}
????}
????_stRemoteAddr?
=?_stCtrlObject.AnalyseAddr(str);

????
return?0;????
}

int?CFTPPasvDataTcpObject::Connect()
{
????_stTcpStreamPtr.reset(
new?ACEX_TcpStream(_szBuffSize));
????
if(_stConnector.connect(*_stTcpStreamPtr.get(),?_stRemoteAddr,?&_stTimeout)?==?0)
????{
????????_stTcpStreamPtr
->block(0);
????}
????
else
????{
????????_stTcpStreamPtr.reset(NULL);
????}

????
if(_stTcpStreamPtr.get()?!=?NULL)
????????
return?0;
????_bOpen?
=?false;
????
return?-1;
}


posted on 2009-07-31 10:22 codejie 閱讀(1337) 評論(14)  編輯 收藏 引用 所屬分類: C++

評論

# re: 輪子:FTP接口實現(xiàn) 2009-08-06 14:27 uwinb

我也做過這樣的輪子,不過我在實現(xiàn)FTP客戶端之前先干了一件事,就是按照流對象的概念封裝了套接口,讓它自己智能地維護(hù)緩沖區(qū)!在單線程環(huán)境下,客戶端也能實現(xiàn)以PORT方式登錄Unix的FTP服務(wù)端。還有遇到一個問題,就是調(diào)用一次recv()不一定就能收全數(shù)據(jù),可能需要反復(fù)測試可讀性和調(diào)用接收函數(shù),這也是封裝套接口的原因之一。  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-08-06 17:28 codejie

我是按照FTP的思想封裝的,分Contral和Data兩個對象,然后再分Pasv和Port兩個Data子對象。
你說到的流對象封裝,我是在Data中作的~
嘿嘿,咱們做輪子的想法都一樣~  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-08-08 19:19 uwinb

FTP其實就是個有問有答的協(xié)商協(xié)議,Pasv和Port只不過是兩種登錄的方式,在我的方案中發(fā)現(xiàn)其中一種失效會自動去嘗試另一種,不管咋的建立聯(lián)接以后的數(shù)據(jù)傳遞沒啥子區(qū)別。所以對你的類框架模型稍有質(zhì)疑,呵呵!
還有涉及訪問網(wǎng)絡(luò)這種充滿不可預(yù)測的事件的對象,你居然不使用異常來反饋錯誤!學(xué)術(shù)討論而已,不必介意我的觀點。  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-08-09 20:16 codejie

先說異常的問題,你說的很對,在第一版本時,實現(xiàn)中都是異常方式,由于外層調(diào)用的代碼不是我寫的,并且不喜歡異常,我被迫改成0和-1方式了,因此也增加了很多自定義的錯誤碼~實話說,我還是喜歡異常方式的,嘿嘿~
關(guān)于PASV和PORT方式,我認(rèn)為不是你說的‘登錄’方式,而應(yīng)該是數(shù)據(jù)傳輸?shù)膬煞N連接模式,當(dāng)然如果你說的‘登錄’就是指這個連接,那么我們就一樣了~我說明一下吧,PASV模式是指在數(shù)據(jù)傳輸時,服務(wù)器端做Server;而PORT模式相反。具體可以參看FTP協(xié)議。
我不知道你方案中的“發(fā)現(xiàn)其中一種失效會自動去嘗試另一種”是何種需求下實現(xiàn)的,我這里只是對兩種模式的對象封裝,至于如何使用這些對象,是上層調(diào)用去決定的。像某些FTP服務(wù)端為了防止‘請求’方式攻擊,而僅支持PORT方式。所以這里的對象自身無需去考慮“失效”和“嘗試”的問題。

我很介意你的觀點,因為我認(rèn)為--不同的思想只有去碰撞,才能共同改善~  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-08 19:57 白云深

謝謝樓主的代碼。

另外有個問題請教一下:“ACEX_TcpStream”這個對象是什么庫里面的,還是樓主自己封裝的?  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-08 22:38 codejie

客氣了~
ACEX_TcpStream類是對Socket的封裝,出自工作中使用的ACEX庫,這個不是我封的,從功能看應(yīng)該基于Socket和Stream兩個基類。把這個類看成Socket流對象就可以了,這個不是重點了。  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-08 23:31 白云深

多謝樓主答復(fù)。

本人是個菜鳥,所以細(xì)節(jié)上有好多問題不明白。  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-09 21:32 codejie

客氣了~有問題,咱一起想~  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-09 21:46 白云深

呵呵,謝謝樓主的熱心。

雖然不恥下問是個好習(xí)慣,但基礎(chǔ)的東西還是要靠自己的學(xué)習(xí),自己不學(xué)習(xí)隨意張口問別人也不是學(xué)習(xí)的好態(tài)度,同時也是浪費別人的時間和自己的智商。不說了,學(xué)習(xí)了,呵呵。以后會經(jīng)常來博主這,向博主請益,博主可要勤奮點哦,博主多寫文章就是對俺們菜鳥最大的幫助。  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-09 22:35 codejie

求你多來問吧,么發(fā)現(xiàn)近來代碼越來越少了嗎?這里都成了我發(fā)牢騷的地方了。你的問題也是讓我前進(jìn)的動力~  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-10 21:39 白云深

今天把博主的代碼整理了一下,暫時調(diào)試了一下port模式。把下面這個函數(shù)

int CFTPDataTcpObject::Read(char*& data, size_t& size)

改為:

int CFTPDataTcpObject::Read(std::string & data)

博主的實現(xiàn)中,用new來動態(tài)分配內(nèi)存,但好像沒有釋放,按博主的實現(xiàn),這個釋放動作應(yīng)該要由上層調(diào)用來完成,不知道我的理解是否正確。如果所說無誤,這是否可以理解為這個接口會造成泄漏或與上層程序有耦合?

另外,如果不用std::string來返回數(shù)據(jù)以防止內(nèi)存泄露,個人以為改為類似于系統(tǒng)調(diào)用ssize_t read (void * buf, unsinged long)的接口更為合理,由返回值指出實際所讀取數(shù)據(jù)的長度,而第二個參數(shù)來指定上層用戶所使用的緩沖區(qū)的大小,但若這樣實現(xiàn)必須考慮用戶一次無法讀取所以數(shù)據(jù)的情況。  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-10 21:42 白云深

暈,剛才又仔細(xì)看了下,那個接口好像在實際應(yīng)用中并不會被調(diào)用,這樣的話上面我懷疑的問題也就不是問題了。  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-12 22:17 codejie

@白云深
這里先說明一下Read和Write,這兩個函數(shù)和Port或者Pasv方式?jīng)]有關(guān)系,就是從Socket上讀數(shù)據(jù)和寫數(shù)據(jù),因此這兩個函數(shù)放在FTP數(shù)據(jù)傳輸鏈路的基類CFTPDataTcpObject中。兩個函數(shù)不同的參數(shù)完成不同的需求,如下:
int Read(char*& data, size_t& size);
用于從Socket接收數(shù)據(jù)到data中,接收的長度放在size中返回;
int Read(std::ofstream& ofile, size_t& size);
用于從Scket接收數(shù)據(jù)到文件ofile中,接收的長度放在size中返回;
int Read(std::ostream& os, size_t& size);
用于從Socket接收數(shù)據(jù)到輸出流os中,接收的長度放在size中返回;
int Write(const char* data, size_t size);
用于將data中的數(shù)據(jù)寫入到Socket中;
int Write(std::ifstream& ifile, size_t& size);
用于將輸入文件ifile的數(shù)據(jù)寫入到Socket中;

在我們使用中,F(xiàn)TP數(shù)據(jù)操作多數(shù)是針對文件的,因此下面兩個函數(shù)方式是最常用的:
int Read(std::ofstream& ofile, size_t& size);
int Write(std::ifstream& ifile, size_t& size);

因此,我覺得你嘗試覆蓋上面的函數(shù)應(yīng)該會被調(diào)用到,除非你不是針對文件操作,就像使用FTP的LIST命令,是將結(jié)果放在輸出流或者一塊空間中。

關(guān)于你的問題:
1.String代替data,這種方式是可行的,只是使用起來應(yīng)該比較危險和不方便,雖然string可以存放非可見字符,但顯示中很少用string來操作他們;簡單地說,你不能確定FTP只是傳文本文件吧?傳個圖片什么的,F(xiàn)TP應(yīng)該支持吧?
2.關(guān)于data被new而沒有delete的問題,先看看函數(shù)聲明:
int Read(char*& data, size_t& size);
可見data是傳出參數(shù),如果函數(shù)里面就delete了,那調(diào)用這個函數(shù)還有什么意義呢?如果data由調(diào)用方new好,但調(diào)用方(上層程序)又怎么預(yù)先知道new多少空間夠呢?這種由函數(shù)自己new,而由調(diào)用方管理的定義方式應(yīng)該算常見的,簡單說當(dāng)使用類似(char*&)這樣的參數(shù)時,就該意識到,使用者有義務(wù)管理好返回的指針。(多說一句:函數(shù)參數(shù)char*和char*&是不同的)
  回復(fù)  更多評論   

# re: 輪子:FTP接口實現(xiàn) 2009-09-14 23:20 白云深

受教了。

呵呵,看著又是指針又是引用有點暈,還是自己寫的代碼太少了。  回復(fù)  更多評論   

公告

Using C++

導(dǎo)航

統(tǒng)計

留言簿(73)

隨筆分類(513)

積分與排名

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲免费观看| 久久综合九色综合欧美狠狠| 国产综合色一区二区三区 | 中文在线资源观看视频网站免费不卡| 99国产精品久久| 国产精品乱码| 欧美成人激情视频免费观看| 亚洲精品永久免费精品| 羞羞答答国产精品www一本| 国产一区二区三区无遮挡| 欧美gay视频激情| 亚洲区在线播放| 国产精品久久午夜夜伦鲁鲁| 蜜桃精品久久久久久久免费影院| 亚洲最快最全在线视频| 老巨人导航500精品| 一区二区三区久久| 91久久精品国产| 国内自拍视频一区二区三区| 欧美日韩综合一区| 久久影院亚洲| 欧美一区二区免费| 中文高清一区| aⅴ色国产欧美| 亚洲精品在线观| 1204国产成人精品视频| 国语自产偷拍精品视频偷| 欧美日本在线观看| 欧美高清视频免费观看| 欧美在线视频一区二区三区| 亚洲精品视频免费观看| 亚洲欧洲精品天堂一级| 久久久久久黄| 久久久99国产精品免费| 一区二区精品国产| 一区二区激情小说| 亚洲专区免费| 亚洲一区国产一区| 亚洲在线观看视频| 欧美一区二区三区视频在线观看| 中日韩男男gay无套| 日韩视频免费观看高清完整版| 亚洲精品乱码久久久久久按摩观| 国产精品亚洲а∨天堂免在线| 欧美欧美天天天天操| 欧美成人r级一区二区三区| 久久青青草原一区二区| 久久综合亚洲社区| 欧美人与禽猛交乱配| 欧美午夜视频网站| 国产精品国产亚洲精品看不卡15| 欧美午夜精品久久久久久久| 欧美日韩国产丝袜另类| 欧美性片在线观看| 国产精品日韩在线| 一区二区三区在线不卡| 亚洲欧洲三级| 亚洲毛片播放| 欧美精品v国产精品v日韩精品| 免费观看成人| 欧美日韩在线综合| 国产亚洲二区| 亚洲乱码国产乱码精品精| 亚洲一级二级在线| 在线观看亚洲精品| 亚洲高清免费| 在线综合亚洲| 久久久97精品| 亚洲精品综合久久中文字幕| 亚洲欧美日韩精品久久奇米色影视| 欧美在线免费观看| 欧美a级片一区| 国产精品亚洲综合色区韩国| 精东粉嫩av免费一区二区三区| 亚洲精品一区二区三区四区高清 | 免费在线观看精品| 国产精品久久9| 激情久久久久久| 亚洲欧美在线免费| 欧美激情在线狂野欧美精品| 亚洲视频一区二区在线观看| 久久综合99re88久久爱| 国产精品女主播在线观看| 激情欧美日韩| 午夜综合激情| 日韩视频久久| 麻豆国产精品va在线观看不卡| 国产精品美女久久福利网站| 日韩午夜av在线| 免费看亚洲片| 午夜精品成人在线| 欧美日韩精品三区| 亚洲国产1区| 亚洲欧美日韩一区二区| 欧美国产日韩a欧美在线观看| 欧美日韩免费一区二区三区| 香港久久久电影| 久久影音先锋| 亚洲专区免费| 欧美成人dvd在线视频| 午夜视频在线观看一区二区三区 | 欧美精品成人| 午夜一区二区三视频在线观看| 欧美亚洲尤物久久| 99国产一区| 久久精品中文| 亚洲欧美日韩一区| 欧美美女bb生活片| 欧美va亚洲va日韩∨a综合色| 国产精品xxxxx| 亚洲日韩成人| 国产综合自拍| 亚洲综合精品一区二区| 亚洲精品国产精品国自产观看浪潮 | 亚洲人人精品| 激情另类综合| 午夜精品影院| 亚洲在线成人| 欧美大片91| 欧美v国产在线一区二区三区| 国产精品网站在线观看| 亚洲开发第一视频在线播放| ●精品国产综合乱码久久久久| 午夜久久黄色| 午夜在线一区二区| 国产精品美女www爽爽爽| 亚洲最黄网站| 亚洲一区bb| 欧美日韩一二三区| 亚洲精品一区二区三区蜜桃久| 亚洲第一毛片| 老司机成人在线视频| 久热精品视频在线| 精久久久久久| 久久免费视频网| 免费看黄裸体一级大秀欧美| 激情一区二区| 久久久91精品| 久久综合给合久久狠狠色 | 欧美激情a∨在线视频播放| 国产婷婷一区二区| 新67194成人永久网站| 亚洲影音先锋| 欧美午夜无遮挡| 正在播放亚洲一区| 香蕉久久国产| 国产欧美精品一区二区色综合| 亚洲一级免费视频| 性色一区二区三区| 国产亚洲精品aa午夜观看| 久久精品国产清自在天天线| 久久午夜精品| 亚洲精品久久久蜜桃| 欧美精品激情| 在线综合亚洲| 欧美在线观看www| 国内揄拍国内精品久久| 乱码第一页成人| 亚洲精品免费看| 午夜宅男欧美| 影音先锋中文字幕一区| 欧美国产成人精品| 亚洲私拍自拍| 久久视频一区二区| 亚洲黄色一区| 国产精品第三页| 久久精品视频免费播放| 亚洲国产电影| 欧美亚洲三级| 亚洲国内在线| 国产精品国产a级| 久久久久久综合网天天| 亚洲国产高清视频| 香蕉成人啪国产精品视频综合网| 一区视频在线看| 欧美视频在线一区| 久久久久久久久伊人| 一本色道久久综合狠狠躁的推荐| 欧美一区二区| 亚洲精选一区二区| 久久中文字幕导航| 亚洲美女视频在线观看| 久久久久久一区二区三区| 亚洲精品久久在线| 国产真实久久| 欧美日韩国产一区精品一区| 欧美一区三区三区高中清蜜桃| 亚洲国产一区二区精品专区| 欧美一区二区三区播放老司机| 亚洲国产精品热久久| 国产精品私拍pans大尺度在线| 欧美ed2k| 久久久久久亚洲精品杨幂换脸| 日韩一级不卡| 欧美激情在线| 欧美大片在线观看一区| 久久精品91久久香蕉加勒比 | 久久欧美中文字幕| 亚洲系列中文字幕| 日韩天堂在线观看|