用VC++编制FTP客户端应用程序

来源: 作者: 2006-11-07 出处:pcdog.com

  • ftp服务器
  • 协议

  •   FTP协议将使用两条单独的TCP连接,一条专用于发送FTP命令,另一条则专用于传递数据。初始建立连接时,服务器在21号端口上接收来自客户端的命令连接。当需要传送数据时(文件列表、文件数据等),客户端向服务器发出Port命令,并进入监听状态,等待来自服务器的数据连接请求。

      首先我们利用VC++ 6.0的AppWizard创建一个基于对话框的应用程序,命名为FtpClientDemo。为程序生成五个基于CAsyncSocket的新类,这里列出主要代码。

      CCommandSocket类的主要代码

      void CCommandSocket::OnReceive(int nErrorCode)

      {

      //这个函数使得服务器的应答消息显示在编辑框上

       char buffer=new char[4096];

       memset(buffer,0,4096);

       this-〉Receive(buffer,1024,0);

      //接收应答消息

       MessageList+=buffer;

       m_ReturnMessage-〉SetWindowText(MessageList);

       delete buffer;

      }

      CFileSocket类的主要代码

        void CFileSocket::OnReceive(int nErrorCode)

      {

      //函数将收到的文件数据写到文件中

       if(File= =NULL)

       { File=new CFile();

       File-〉Open(FileName,CFile::modeWrite|CFile::modeCreate);

       }

       charbuffer=new char[4096];

       memset(buffer,0,4096);

       this-〉Receive(buffer,4096,0);

       ReceiveString=buffer;

       File-〉Write(ReceiveString,ReceiveString.GetLength( ));

       delete buffer;

      }

      CReceiveSocket类的主要代码

      void CReceiveSocket::OnReceive(int nErrorCode)

      {

      //接收服务器传来的文件列表消息

       CString ReceiveString,Temp;

       charbuffer=new char[4096];

       memset(buffer,0,4096);

       this-〉Receive(buffer,4096,0); //接收消息

       ReceiveString+=buffer;

       delete buffer;

      //将文件列表从收到的消息字符串中分离出来,并显示在列表框中

       while(!ReceiveString.IsEmpty())

       { int p=ReceiveString.Find("\r\n");

      if(p!=-1)

      { Temp=ReceiveString.Left(p);

       ReceiveString=ReceiveString.Right(ReceiveString.GetLength()-p-2);

      DisplayMessage-〉AddString(Temp);

       }

      }

      }

      CPortSocket类主要代码

      void CPortSocket::OnAccept(int nErrorCode)

      {

      //根据不同的标志选择相应的数据连接类,以接受服务器端的数据连接请求

       if(Flag= =LISTFILE)

      //若程序要求对目录进行列表,则采用CReceiveSocket类

       {DataSocket=new CReceiveSocket(FileList);

       this-〉Accept(DataSocket);

       }

       else if(Flag= =DOWNLOAD)

      //若程序要求下载文件,则生成CFileSocket类的对象

      {FileSocket=new CFileSocket(FileName);

      this-〉Accept(FileSocket);

       }

      }

      主对话框类CFtpClient- DemoDlg的主要代码

        void CFtpClientDemoDlg::OnFileList()

      //响应“文件列表”按钮、列表目录

      { CString Temp;

       if(ControlSocket= =NULL)

       {

      //连接到FTP服务器

      ControlSocket=new CCommandSocket(&&m_ReturnMessage);

      ControlSocket-〉Create();

      m_Server.GetWindowText(Temp);

      ControlSocket-〉Connect(Temp,21);

      //FTP服务器在21号端口接收连接

       }

       m_User.GetWindowText(Temp);

       Temp="USER "+Temp+"\r\n";

       ControlSocket-〉Send(Temp,Temp.GetLength(),0);

      //发User命令,验证用户

       m_Pass.GetWindowText(Temp); //m_Pass为“口令”编辑框的对应控制

       Temp="PASS "+Temp+"\r\n";

       ControlSocket-〉Send(Temp,Temp.GetLength(),0);

      //发Pass命令,校验口令

       LisentPort(LISTFILE);

      //数据连接的对象为目录列表

       ControlSocket-〉Send("LIST \r\n",7 ,0);

      //发List命令,要求列表目录

      }

      void CFtpClientDemoDlg::OnDownLoad( )

      //下载文件

      {

       CString String;

       LisentPort(DOWNLOAD);

      //获得要下戴文件的文件名

       m_LocalFile.GetWindowText(String);

      // m_LocalFile为“文件名”编辑框的对应控制

       String="RETR "+String+"\r\n";

       ControlSocket-〉Send(String,String.GetLength( ),0);

      //发RETR命令,下载文件

      }

      void CFtpClientDemoDlg::LisentPort(UINT Flag)

      {

      //根据要求选择不同的数据连接对象

       if(LisentSocket!=NULL)

      //清空LisentSocket

       { LisentSocket-〉Close();

       delete LisentSocket;

       LisentSocket=NULL;

       }

       if(Flag= =LISTFILE)

      //如果为目录列表数据连接对象

       { LisentSocket=new CPortSocket(LISTFILE);

       LisentSocket-〉SetListBox(&&m_FileList);

      //传列表框到CLisentSocket类中

       }

       else if(Flag= =DOWNLOAD)

      //如果为文件传输数据连接对象

       { CString String;

       m_LocalFile.GetWindowText(String);

       LisentSocket=new CPortSocket(DOWNLOAD);

       LisentSocket-〉SetFileName(String);

      //传文件名到CLisentSocket类中

       }

       LisentSocket-〉Create();

      //建立Socket并进行监听,等待FTP服务器进行数据连接

       LisentSocket-〉Listen();

      //取得数据连接Socket的IP地址和监听端口,并把它们作为Port命令的参数

       SOCKADDR_IN listing_address, control_address;

       int addr_size;

       addr_size = sizeof(listing_address);

       LisentSocket-〉GetSockName((SOCKADDR )&&listing_address, &&addr_size); //
    取IP地址

       ControlSocket-〉GetSockName((SOCKADDR )&&control_address, &&addr_size); /
    /取端口

      unsigned char port = (unsigned char )&&(listing_address.sin_port);

       unsigned char host = (unsigned char )&&(control_address.sin_addr);

       CString strBuffer;

       strBuffer.Format("PORT %i,%i,%i,%i,%i,%i\r\n",(int)host[0], (int)host[1], (
    int)host[2], (int)host[3],(int)port[0], (int)port[1]);

       ControlSocket-〉Send(strBuffer,strBuffer.GetLength(),0);

      //发送Port命令,进行数据连接

      }

      以上代码在VC++ 6.0、Windows 98上运行通过。


    更多内容请看PCdog.com--FTP服务器FTP的设置与应用FTP协议专题
    上一篇:用VC++编写CGI程序
    下一篇:用VC++遍历目录