首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 计算机考试 > 等级考试 > 复习指导 >

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

2009-03-02 
当需要传送数据时(文件列表、文件数据等),客户端向服务器发出Port命令,并进入监听状态,等待来自服务器的数据连接请求。

    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上运行通过。

 

3COME考试频道为您精心整理,希望对您有所帮助,更多信息在http://www.reader8.com/exam/

热点排行