现在的位置: 首页 > 综合 > 正文

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

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

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

  CCommandSocket类的主要代码 </p> <p>  void CCommandSocket::OnReceive(int nErrorCode) </p> <p>  { </p> <p>  //这个函数使得服务器的应答消息显示在编辑框上 </p> <p>   char buffer=new char[4096]; </p> <p>   memset(buffer,0,4096); </p> <p>   this-〉Receive(buffer,1024,0); </p> <p>  //接收应答消息 </p> <p>   MessageList+=buffer; </p> <p>   m_ReturnMessage-〉SetWindowText(MessageList); </p> <p>   delete buffer; </p> <p>  } </p> <p>  CFileSocket类的主要代码 </p> <p>    void CFileSocket::OnReceive(int nErrorCode) </p> <p>  { </p> <p>  //函数将收到的文件数据写到文件中 </p> <p>   if(File= =NULL) </p> <p>   { File=new CFile(); </p> <p>   File-〉Open(FileName,CFile::modeWrite|CFile::modeCreate); </p> <p>   } </p> <p>   charbuffer=new char[4096]; </p> <p>   memset(buffer,0,4096); </p> <p>   this-〉Receive(buffer,4096,0); </p> <p>   ReceiveString=buffer; </p> <p>   File-〉Write(ReceiveString,ReceiveString.GetLength( )); </p> <p>   delete buffer; </p> <p>  } </p> <p>  CReceiveSocket类的主要代码 </p> <p>  void CReceiveSocket::OnReceive(int nErrorCode) </p> <p>  { </p> <p>  //接收服务器传来的文件列表消息 </p> <p>   CString ReceiveString,Temp; </p> <p>   charbuffer=new char[4096]; </p> <p>   memset(buffer,0,4096); </p> <p>   this-〉Receive(buffer,4096,0); //接收消息 </p> <p>   ReceiveString+=buffer; </p> <p>   delete buffer; </p> <p>  //将文件列表从收到的消息字符串中分离出来,并显示在列表框中 </p> <p>   while(!ReceiveString.IsEmpty()) </p> <p>   { int p=ReceiveString.Find("\r\n"); </p> <p>  if(p!=-1) </p> <p>  { Temp=ReceiveString.Left(p); </p> <p>   ReceiveString=ReceiveString.Right(ReceiveString.GetLength()-p-2); </p> <p>  DisplayMessage-〉AddString(Temp); </p> <p>   } </p> <p>  } </p> <p>  } </p> <p>  CPortSocket类主要代码 </p> <p>  void CPortSocket::OnAccept(int nErrorCode) </p> <p>  { </p> <p>  //根据不同的标志选择相应的数据连接类,以接受服务器端的数据连接请求 </p> <p>   if(Flag= =LISTFILE) </p> <p>  //若程序要求对目录进行列表,则采用CReceiveSocket类 </p> <p>   {DataSocket=new CReceiveSocket(FileList); </p> <p>   this-〉Accept(DataSocket); </p> <p>   } </p> <p>   else if(Flag= =DOWNLOAD) </p> <p>  //若程序要求下载文件,则生成CFileSocket类的对象 </p> <p>  {FileSocket=new CFileSocket(FileName); </p> <p>  this-〉Accept(FileSocket); </p> <p>   } </p> <p>  } </p> <p>  主对话框类CFtpClient- DemoDlg的主要代码 </p> <p>    void CFtpClientDemoDlg::OnFileList() </p> <p>  //响应“文件列表”按钮、列表目录 </p> <p>  { CString Temp; </p> <p>   if(ControlSocket= =NULL) </p> <p>   { </p> <p>  //连接到FTP服务器 </p> <p>  ControlSocket=new CCommandSocket(&amp;&amp;m_ReturnMessage); </p> <p>  ControlSocket-〉Create(); </p> <p>  m_Server.GetWindowText(Temp); </p> <p>  ControlSocket-〉Connect(Temp,21); </p> <p>  //FTP服务器在21号端口接收连接 </p> <p>   } </p> <p>   m_User.GetWindowText(Temp); </p> <p>   Temp="USER "+Temp+"\r\n"; </p> <p>   ControlSocket-〉Send(Temp,Temp.GetLength(),0); </p> <p>  //发User命令,验证用户 </p> <p>   m_Pass.GetWindowText(Temp); //m_Pass为“口令”编辑框的对应控制 </p> <p>   Temp="PASS "+Temp+"\r\n"; </p> <p>   ControlSocket-〉Send(Temp,Temp.GetLength(),0); </p> <p>  //发Pass命令,校验口令 </p> <p>   LisentPort(LISTFILE); </p> <p>  //数据连接的对象为目录列表 </p> <p>   ControlSocket-〉Send("LIST \r\n",7 ,0); </p> <p>  //发List命令,要求列表目录 </p> <p>  } </p> <p>  void CFtpClientDemoDlg::OnDownLoad( ) </p> <p>  //下载文件 </p> <p>  { </p> <p>   CString String; </p> <p>   LisentPort(DOWNLOAD); </p> <p>  //获得要下戴文件的文件名 </p> <p>   m_LocalFile.GetWindowText(String); </p> <p>  // m_LocalFile为“文件名”编辑框的对应控制 </p> <p>   String="RETR "+String+"\r\n"; </p> <p>   ControlSocket-〉Send(String,String.GetLength( ),0); </p> <p>  //发RETR命令,下载文件 </p> <p>  } </p> <p>  void CFtpClientDemoDlg::LisentPort(UINT Flag) </p> <p>  { </p> <p>  //根据要求选择不同的数据连接对象 </p> <p>   if(LisentSocket!=NULL) </p> <p>  //清空LisentSocket </p> <p>   { LisentSocket-〉Close(); </p> <p>   delete LisentSocket; </p> <p>   LisentSocket=NULL; </p> <p>   } </p> <p>   if(Flag= =LISTFILE) </p> <p>  //如果为目录列表数据连接对象 </p> <p>   { LisentSocket=new CPortSocket(LISTFILE); </p> <p>   LisentSocket-〉SetListBox(&amp;&amp;m_FileList); </p> <p>  //传列表框到CLisentSocket类中 </p> <p>   } </p> <p>   else if(Flag= =DOWNLOAD) </p> <p>  //如果为文件传输数据连接对象 </p> <p>   { CString String; </p> <p>   m_LocalFile.GetWindowText(String); </p> <p>   LisentSocket=new CPortSocket(DOWNLOAD); </p> <p>   LisentSocket-〉SetFileName(String); </p> <p>  //传文件名到CLisentSocket类中 </p> <p>   } </p> <p>   LisentSocket-〉Create(); </p> <p>  //建立Socket并进行监听,等待FTP服务器进行数据连接 </p> <p>   LisentSocket-〉Listen(); </p> <p>  //取得数据连接Socket的IP地址和监听端口,并把它们作为Port命令的参数 </p> <p>   SOCKADDR_IN listing_address, control_address; </p> <p>   int addr_size; </p> <p>   addr_size = sizeof(listing_address); </p> <p>   LisentSocket-〉GetSockName((SOCKADDR )&amp;&amp;listing_address, &amp;&amp;addr_size); //<br /> 取IP地址 </p> <p>   ControlSocket-〉GetSockName((SOCKADDR )&amp;&amp;control_address, &amp;&amp;addr_size); /<br /> /取端口 </p> <p>  unsigned char port = (unsigned char )&amp;&amp;(listing_address.sin_port); </p> <p>   unsigned char host = (unsigned char )&amp;&amp;(control_address.sin_addr); </p> <p>   CString strBuffer; </p> <p>   strBuffer.Format("PORT %i,%i,%i,%i,%i,%i\r\n",(int)host[0], (int)host[1], (<br /> int)host[2], (int)host[3],(int)port[0], (int)port[1]); </p> <p>   ControlSocket-〉Send(strBuffer,strBuffer.GetLength(),0); </p> <p>  //发送Port命令,进行数据连接 </p> <p>  } </p> <p>  以上代码在VC++ 6.0、Windows 98上运行通过。<br />

抱歉!评论已关闭.