⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftpclient.cpp

📁 实现了wince 客户端上传下载查看文件及目录的功能接口d
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      (*it)->OnPostSendFile(strLocalFile, strRemoteFile, lLocalFileSize);

   return fRet;
}

/// Executes a commando that result in a communication over the data port.
/// @param[in] crDatachannelCmd Command to be executeted.
/// @param[in] strPath Parameter for the command usually a path.
/// @param[in] representation see documentation of CFTPClient::CRepresentation
/// @param[in] fPasv see documentation of CFTPClient::Passive
/// @param[in] dwByteOffset Server marker at which file transfer is to be restarted.
/// @param[in] pObserver Object for observing the execution of the command.
bool CFTPClient::ExecuteDatachannelCommand(const CDatachannelCmd& crDatachannelCmd, const tstring& strPath, const CRepresentation& representation, 
                                           bool fPasv, DWORD dwByteOffset, ITransferNotification* pObserver) const
{
   if( m_fTransferInProgress )
      return false;

   if( !IsConnected() )
      return false;

   // check representation
   if( m_apCurrentRepresentation.get()==NULL )
      m_apCurrentRepresentation.reset(new CRepresentation(CType::ASCII()));
   
   if( representation!=*m_apCurrentRepresentation )
   {
      // transmit representation to server
      if( RepresentationType(representation)!=FTP_OK )
         return false;
      *m_apCurrentRepresentation = representation;
   }

   std::auto_ptr<IBlockingSocket> apSckDataConnection(m_apSckControlConnection->CreateInstance());

   if( fPasv )
   {
      if( !OpenPassiveDataConnection(*apSckDataConnection, crDatachannelCmd, strPath, dwByteOffset) )
         return false;
   }
   else
   {
      if( !OpenActiveDataConnection(*apSckDataConnection, crDatachannelCmd, strPath, dwByteOffset) )
         return false;
   }

   const bool fTransferOK = TransferData(crDatachannelCmd, pObserver, *apSckDataConnection);
   
   apSckDataConnection->Close();

   // get response from ftp server
   CReply Reply;
   if( !fTransferOK || !GetResponse(Reply) || !Reply.Code().IsPositiveCompletionReply() )
      return false;

   return true;
}

/// Executes a commando that result in a communication over the data port.
/// @param[in] crDatachannelCmd Command to be executeted.
/// @param[in] pObserver Object for observing the execution of the command.
/// @param[in] sckDataConnection Socket which is used for sending/receiving data.
bool CFTPClient::TransferData(const CDatachannelCmd& crDatachannelCmd, ITransferNotification* pObserver, IBlockingSocket& sckDataConnection) const
{
   switch( crDatachannelCmd.AsEnum() )
   {
   case CDatachannelCmd::cmdSTOR:
   case CDatachannelCmd::cmdSTOU:
   case CDatachannelCmd::cmdAPPE:
      {
         if( !SendData(pObserver, sckDataConnection) )
            return false;
      }
      break;
   case CDatachannelCmd::cmdRETR:
   case CDatachannelCmd::cmdLIST:
   case CDatachannelCmd::cmdNLST:
      if( !ReceiveData(pObserver, sckDataConnection) )
         return false;
      break;
   default:
      ASSERT( false );
      return false;
   }
   return true;
}

/// Opens an active data connection.
/// @param[out] sckDataConnection
/// @param[in] crDatachannelCmd Command to be executeted.
/// @param[in] strPath Parameter for the command usually a path.
/// @param[in] dwByteOffset Server marker at which file transfer is to be restarted.
bool CFTPClient::OpenActiveDataConnection(IBlockingSocket& sckDataConnection, const CDatachannelCmd& crDatachannelCmd, const tstring& strPath, DWORD dwByteOffset) const
{
   std::auto_ptr<IBlockingSocket> apSckServer(m_apSckControlConnection->CreateInstance());

   USHORT ushLocalSock = 0;
   try
   {
      // INADDR_ANY = ip address of localhost
      // second parameter "0" means that the WINSOCKAPI ask for a port
      CSockAddr csaAddressTemp(INADDR_ANY, 0);
      apSckServer->Create(SOCK_STREAM);
      apSckServer->Bind(csaAddressTemp);
      apSckServer->GetSockAddr(csaAddressTemp);
      ushLocalSock=csaAddressTemp.Port();
      apSckServer->Listen();
   }
   catch(CBlockingSocketException& blockingException)
   {
      ReportError(blockingException.GetErrorMessage(), CCnv::ConvertToTString(__FILE__), __LINE__);
      apSckServer->Cleanup();
      return false;
   }

   // get own ip address
   CSockAddr csaLocalAddress;
   m_apSckControlConnection->GetSockAddr(csaLocalAddress);

   // transmit the socket (ip address + port) to the server
   // the ftp server establishes then the data connection
   if( DataPort(csaLocalAddress.DottedDecimal(), ushLocalSock)!=FTP_OK )
      return false;

   // if resuming is activated then set offset
   if( m_fResumeIfPossible && 
      (crDatachannelCmd==CDatachannelCmd::cmdSTOR || crDatachannelCmd==CDatachannelCmd::cmdRETR || crDatachannelCmd==CDatachannelCmd::cmdAPPE ) &&
       (dwByteOffset!=0 && Restart(dwByteOffset)!=FTP_OK) )
      return false;

   // send FTP command RETR/STOR/NLST/LIST to the server
   CReply Reply;
   if( !SendCommand(GetCmdString(crDatachannelCmd, strPath), Reply) ||
       !Reply.Code().IsPositivePreliminaryReply() )
      return false;

   // accept the data connection
   CSockAddr sockAddrTemp;
   if( !apSckServer->Accept(sckDataConnection, sockAddrTemp) )
      return false;

   return true;
}

/// Opens a passive data connection.
/// @param[out] sckDataConnection
/// @param[in] crDatachannelCmd Command to be executeted.
/// @param[in] strPath Parameter for the command usually a path.
/// @param[in] dwByteOffset Server marker at which file transfer is to be restarted.
bool CFTPClient::OpenPassiveDataConnection(IBlockingSocket& sckDataConnection, const CDatachannelCmd& crDatachannelCmd, const tstring& strPath, DWORD dwByteOffset) const
{
   ULONG   ulRemoteHostIP = 0;
   USHORT  ushServerSock  = 0;

   // set passive mode
   // the ftp server opens a port and tell us the socket (ip address + port)
   // this socket is used for opening the data connection 
   if( Passive(ulRemoteHostIP, ushServerSock)!=FTP_OK )
      return false;

   // establish connection
   CSockAddr sockAddrTemp;
   try
   {
      sckDataConnection.Create(SOCK_STREAM);
      CSockAddr csaAddress(ulRemoteHostIP, ushServerSock); 
      sckDataConnection.Connect(csaAddress);
   }
   catch(CBlockingSocketException& blockingException)
   {
      ReportError(blockingException.GetErrorMessage(), CCnv::ConvertToTString(__FILE__), __LINE__);
      sckDataConnection.Cleanup();
      return false;
   }

   // if resuming is activated then set offset
   if( m_fResumeIfPossible && 
      (crDatachannelCmd==CDatachannelCmd::cmdSTOR || crDatachannelCmd==CDatachannelCmd::cmdRETR || crDatachannelCmd==CDatachannelCmd::cmdAPPE ) &&
       (dwByteOffset!=0 && Restart(dwByteOffset)!=FTP_OK) )
      return false;

   // send FTP command RETR/STOR/NLST/LIST to the server
   CReply Reply;
   if( !SendCommand(GetCmdString(crDatachannelCmd, strPath), Reply) ||
       !Reply.Code().IsPositivePreliminaryReply() )
      return false;

   return true;
}

/// Sends data over a socket to the server.
/// @param[in] pObserver Object for observing the execution of the command.
/// @param[in] sckDataConnection Socket which is used for the send action.
bool CFTPClient::SendData(ITransferNotification* pObserver, IBlockingSocket& sckDataConnection) const
{
   try
   {
      m_fTransferInProgress=true;

      int iNumWrite;
      size_t bytesRead;

      pObserver->OnPreBytesSend(m_vBuffer, bytesRead);

      while( !m_fAbortTransfer && bytesRead!=0 )
      {
         iNumWrite = sckDataConnection.Write(&(*m_vBuffer.begin()), static_cast<int>(bytesRead), mc_uiTimeout);
         ASSERT( iNumWrite == static_cast<int>(bytesRead) );

         for( TObserverSet::const_iterator it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )
            (*it)->OnBytesSent(m_vBuffer, iNumWrite);

         pObserver->OnPreBytesSend(m_vBuffer, bytesRead);
      }

      m_fTransferInProgress=false;
      if( m_fAbortTransfer )
      {
         Abort();
         return false;
      }

   }
   catch(CBlockingSocketException& blockingException)
   {
      m_fTransferInProgress=false;
      ReportError(blockingException.GetErrorMessage(), CCnv::ConvertToTString(__FILE__), __LINE__);
      sckDataConnection.Cleanup();
      return false;
   }

   return true;
}

/// Receives data over a socket from the server.
/// @param[in] pObserver Object for observing the execution of the command.
/// @param[in] sckDataConnection Socket which is used for receiving the data.
bool CFTPClient::ReceiveData(ITransferNotification* pObserver, IBlockingSocket& sckDataConnection) const
{
   try
   {
      m_fTransferInProgress = true;

      for( TObserverSet::const_iterator it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )
         (*it)->OnBeginReceivingData();

      int iNumRead=sckDataConnection.Receive(&(*m_vBuffer.begin()), static_cast<int>(m_vBuffer.size()), mc_uiTimeout);
      long lTotalBytes = iNumRead;
      while( !m_fAbortTransfer && iNumRead!=0 )
      {
         for( TObserverSet::const_iterator it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )
            (*it)->OnBytesReceived(m_vBuffer, iNumRead);

         pObserver->OnBytesReceived(m_vBuffer, iNumRead);

         iNumRead=sckDataConnection.Receive(&(*m_vBuffer.begin()), static_cast<int>(m_vBuffer.size()), mc_uiTimeout);
         lTotalBytes += iNumRead;
      }

      for( TObserverSet::const_iterator it2=m_setObserver.begin(); it2!=m_setObserver.end(); it2++ )
         (*it2)->OnEndReceivingData(lTotalBytes);

      m_fTransferInProgress=false;
      if( m_fAbortTransfer )
      {
         Abort();
         return false;
      }
   }
   catch(CBlockingSocketException& blockingException)
   {
      m_fTransferInProgress=false;
      ReportError(blockingException.GetErrorMessage(), CCnv::ConvertToTString(__FILE__), __LINE__);
      sckDataConnection.Cleanup();
      return false;
   }

   return true;
}

/// Returns the command string for a specific command.
/// @param[in] crDatachannelCmd Command for which the string should be returned.
/// @param[in] strPath Parameter which have to be added to the command.
tstring CFTPClient::GetCmdString(const CDatachannelCmd& crDatachannelCmd, const tstring& strPath) const
{
   switch( crDatachannelCmd.AsEnum() )
   {
   case CDatachannelCmd::cmdLIST: return strPath.empty()?_T("LIST"):_T("LIST ") + strPath;
   case CDatachannelCmd::cmdNLST: return strPath.empty()?_T("NLST"):_T("NLST ") + strPath;
   case CDatachannelCmd::cmdSTOR: return _T("STOR ") + strPath;
   case CDatachannelCmd::cmdSTOU: return _T("STOU ") + strPath;
   case CDatachannelCmd::cmdRETR: return _T("RETR ") + strPath;
   case CDatachannelCmd::cmdAPPE: return _T("APPE ") + strPath;
   default:
      ASSERT( false );
   }
   return _T("");
}

/// Sends a command to the server.
/// @param[in] strCommand Command to send.
bool CFTPClient::SendCommand(const tstring& strCommand) const
{
   if( !IsConnected() )
      return false;

   try
   {
      for( TObserverSet::const_iterator it=m_setObserver.begin(); it!=m_setObserver.end(); it++ )
         (*it)->OnSendCommand(strCommand);
      m_apSckControlConnection->Write((CCnv::ConvertToString(strCommand) + "\r\n").c_str(), static_cast<int>(strCommand.length())+2, mc_uiTimeout);
   }
   catch(CBlockingSocketException& blockingException)
   {
      ReportError(blockingException.GetErrorMessage(), CCnv::ConvertToTString(__FILE__), __LINE__);
      const_cast<CFTPClient*>(this)->m_apSckControlConnection->Cleanup();
      return false;
   }

   return true;
}

/// Sends a command to the server.
/// @param[in]  strCommand Command to send.
/// @param[out] Reply The Reply of the server to the sent command.
bool CFTPClient::SendCommand(const tstring& strCommand, CReply& Reply) const
{
   if( !SendCommand(strCommand) || !GetResponse(Reply) )
      return false;
   return true;
}

/// This function gets the server response.
/// A server response can exists of more than one line. This function
/// returns the full response (multiline).
/// @param[out] Reply Reply of the server to a command.
bool CFTPClient::GetResponse(CReply& Reply) const
{
   tstring strResponse;
   if( !GetSingleResponseLine(strResponse) )
      return false;

   if( strResponse.length()>3 && strResponse.at(3)==_T('-') )
   {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -