正文:

一、FTP通信原理简述

1.1 FTP简介

FTP是基于TCP/IP协议的一个应用协议。主要实现在不同的计算机之间的数据共享。FTP 采用的是C/S模式。客户既可以下载文件也可以上传文件。当然,FTP给用户一定的权限。用户只能在权限下使用。目前,FTP的服务器种类很多,比如常用的SERV-U,客户端程序也很多,比如:CuteFTP。WINDOWS也提供了一个FTP客户程序。它们都根据相同的协议标准来设计的,具体协议内容可参考RFC文档。

SERV-U工作界面

windows提供的客户端

1.2 FTP工作原理

FTP工作原理与其它的应用协议有些不同。它是用两个端口进行通信的。一个端口用于命令交互。这个端口在用户连接之后一直保持;而另一个端口只是在数据传时打开(比如:上传文件,下载文件,获取服务端文件列表),在数据传输时有两种不同的模式,一是用户开通这个数据端口,这种模式叫做主动模式;二是服务器提供一个接口,这个模式叫被动模式。

FTP原理图

1.3 用户登录

FTP服务器提供了用户的访问权限,有的服务器可以匿名登录,有的服务器要求用户使用密码登录。在每一个与登录有关的命令时,服务器都会有一个返回信息。

下面显示了一个登录过程:

1.4 数据传输

在FTP中可以定义数据的传输格式,比如:二进制(进行图象和应用程序传输这种格式)。下面是一个传输过程:

二、FTP命令

在WINDOWS中提供的命令不是FTP的标准命令。有些命令是许多命令的合集。而FTP标准命令,每发送一个,服务器就会做出一个相应的动作,并把认证信息发送给用户。

具体的命令可以参照有关的资料

三、实例

在这里我们用一个FTP客户端来说明以上的知识。这里面主要是一个封装的类。

CFTPClient这个类实现的文件的上传与下载并能获得服务端文件的信息。

1.1 CFTPClient类

class  CFTPClient 

... { 

//成员变量 

private: 

CSocket *m_pSocket; 

CArchive *m_pRxarch; 

CArchive *m_pTxarch; 

CSocketFile *m_psfSokFile; 

CString m_strMsg;//服务器发回的消息 

CString m_fc; 

CftpclientDlg *m_pWnd; //用于对窗口的操作 

CByteArray m_btBuf; 

//成员函数 

public: 

CFTPClient(void); 

~CFTPClient(void); 

//发送命令到服务器 

BOOL FtpCommand (CString strCommand); 

//登录到FTP服务器,这个函数只支持在没有防火墙的时候 

BOOL LogOnToserver ( CString strHostname , int nHostPort , CString strUserName , CString strPassword ); 

//退出服务器 

void LogOffServer(); 

//上传下载文件 

BOOL MoveFile (CString strRemoteFile,CString strLocalFile , BOOL bPasv , BOOL bGet); 

//列出文件列表 

BOOL List(); 

void ProcessList(); 

//获取一行信息 

BOOL GetLine(int ndx,CString &strLine); 

//发送数据 

BOOL WriteStr(CString strOutPut); 

//接收数据 

BOOL ReadStr(); 

//设置窗口 

void SetWnd(CftpclientDlg *pWnd); 

//发送信息 

void SetMessage(CString strMsg); 

//获取文件信息 

BOOL GetFtpFileInfo(int ndx,FTP_FILE_INFO &ftpFileInfo); 

protected: 

//读取服务器发送的信息 

BOOL ReadStr2(); 

//打开通道 

BOOL OpenControlChannel(CString strServerHost , int nServerPort); 

//关闭通道 

void CloseControlChannel(); 

} ; 

1.2  登录函数 

I/**///// 

//  

//  函数:BOOL CFTPClient::LogOnToserver () 

//  

//  描述: 

// 这个函数用于登录到FTP服务器,在这个函数没有对系统的防火墙作// 进一步分析, 

// 读者可以进一步扩展它的功能 

//  

//  

//  参数: 

//  -strHostname 登录的主机名 

//  -nHostPort 主机端口 

//  -strUserName 用户名 

//  -strPassword 用户密码 

//  返回: 

//  -BOOL 成功返回 TRUE 否则返回 FALSE 

//  

// //吴庆民 2005.4.19 

/**//// 

BOOL CFTPClient::LogOnToserver (CString strHostname, int  nHostPort,CString strUserName,CString strPassword) 

... { 

if (!this->OpenControlChannel (strHostname,21)) return FALSE; 

if(!this->ReadStr ()) return FALSE; 

this->SetMessage (this->m_strMsg ); 

//发送一个空消息 

CString temp; 

temp = "USER " + strUserName + " "; 

//发送用户名 

if (!this->WriteStr (temp)) 

...{ 

return FALSE; 



if (!this->ReadStr ()) return FALSE; 

this->SetMessage (this->m_strMsg ); 

//发送密码 

temp = "PASS " + strPassword + " "; 

if (!this->WriteStr (temp)) return FALSE; 

if (!this->ReadStr ()) return FALSE; 

this->SetMessage (this->m_strMsg ); 

return TRUE; 

}  

这个函数主要是联接服务器打开一个通道用于命令传输。这个通道是全双工的。 

1.3  上传下载文件 

/**////// 

//  

//  函数:BOOL CFTPClient::MoveFile () 

//  

//  描述: 

//  上传或下载文件,不支持多线程,可以在这个函数上进行一下扩展 

//  

//  

//  参数: 

//  -strRemoteFile 远程文件名 

//  -strLocalFile 本地文件名 

//  -bPasv 是否为被动模式传输 

//  -bGet 是否为下载文件 

//  

//  返回: 

//  -BOOL 成功返回 TRUE 否则返回 FALSE 

//  

// //吴庆民 2005.4.19 

/**/// 

BOOL CFTPClient::MoveFile (CString strRemoteFile,CString strLocalFile,BOOL bPasv,BOOL bGet) 

... { 

CFile flDataFile; 

CString strCommand ; 

int pos = 0; 

UINT uServSock,uLocalSock; 

CString strHost; 

CSocket sServ; 

CAsyncSocket asListen; 

int i=0,j=0,num,numread,numsent; 

CString strTemp; 

const int BUFSIZE = 4096; 

char cbuf[BUFSIZE]; 

if (!flDataFile.Open (strLocalFile,(bGet?CFile::modeCreate|CFile::modeWrite:CFile::modeRead))) 

...{ 

this->SetMessage ("上传或下载的文件在本地不能打开!"); 

return FALSE; 



//准备传输 

strCommand = "TYPE I  "; 

if (!this->WriteStr (strCommand)) return FALSE; 

if (!this->ReadStr ()) return FALSE; 

this->SetMessage (this->m_strMsg ); 

if (bPasv) 

...{ 

strCommand = "PASV  "; 

if (!this->WriteStr (strCommand)) return FALSE; 

if (!this->ReadStr ()) return FALSE; 

this->SetMessage (this->m_strMsg ); 

//if ((==-1&&(j=this->m_strMsg.Find ("/)"))==-1) return FALSE; 

i=this->m_strMsg.Find ("("); 

j=this->m_strMsg.Find (")"); 

if (i==-1||j==-1) 

...{ 

this->SetMessage ("响应错误!"); 



strTemp = this->m_strMsg.Mid (i+1,(j-i)-1); 

i = strTemp.ReverseFind (','); 

uServSock = atol(strTemp.Right (strTemp.GetLength () - (i+1))); 

strTemp = strTemp.Left (i); 

//this->SetMessage (strTemp); 

i = strTemp.ReverseFind (','); 

uServSock += 256*atol(strTemp.Right (strTemp.GetLength () - (i+1))); 

strHost = strTemp.Left (i); 

while(1) 

...{ 

if ((i=strHost.Find (','))==-1) break; 

strHost.SetAt (i,'.'); 



//this->SetMessage (strHost); 

//CString temp; 

//temp.Format (strHost+" %d",uServSock ); 

//this->SetMessage (temp); 



else 

...{ 

if (!this->m_pSocket->GetSockName (strHost,uLocalSock)) return FALSE; 

while(1) 

...{ 

if ((i=strHost.Find ("."))==-1) break; 

strHost.SetAt (i,','); 



if (!(sServ.Create ())||!(sServ.Listen ())) return FALSE; 

if(!sServ.GetSockName (strTemp,uLocalSock )) return FALSE; 

strHost.Format (strHost+",%d,%d",uLocalSock/256,uLocalSock%256); 

strCommand = "PORT " + strHost ; 

strCommand += " "; 

if (!(this->WriteStr (strCommand))) return FALSE; 

if (!(this->ReadStr ())) return FALSE; 

this->SetMessage (this->m_strMsg ); 



//发送下载或上传命令 

if (bGet) 

...{ 

strCommand = "RETR" + strRemoteFile; 

strCommand += " "; 



else 

...{ 

strCommand = "STOR" + strRemoteFile; 

strCommand += " "; 



if (!this->WriteStr (strCommand)) return FALSE; 

if (bPasv) 

...{ 

if (!(asListen.Create ()) ) 

return FALSE; 

asListen.Connect (strHost, uServSock); 



if (!this->ReadStr ()) return FALSE; 

this->SetMessage (this->m_strMsg ); 

if (this->m_fc != "1") 

...{ 

this->SetMessage ("文件传输不成功!"); 

return FALSE; 



if(!bPasv&&!sServ.Accept (asListen)) return FALSE; 

//数据传输 

DWORD lpArgument; 

if (!asListen.AsyncSelect ()||!asListen.IOCtl (FIONBIO,&lpArgument)) return FALSE; 

while(1) 

...{ 

TRY 

...{ 

if (bGet) 

...{ 

if (!(num=asListen.Receive (cbuf,BUFSIZE,0))) 

break; 

else 

flDataFile.Write (cbuf,num); 



else 

...{ 

if (!(numread = flDataFile.Read (cbuf,BUFSIZE))) 

break; 

else 

if (!(numsent = asListen.Send (cbuf,numread,0))) break; 

if (numread != numsent) 

flDataFile.Seek (numsent - numread,CFile::current); 

pos += numsent; 

m_pWnd ->SetPos(pos); 





CATCH(CException ,e) 

...{ 

this->SetMessage ("数据传输过程中被中断!"); 

return FALSE; 



END_CATCH 



asListen.Close (); 

flDataFile.Close (); 

if (!this->WriteStr (" ")) return FALSE; 

this->ReadStr (); 

this->SetMessage (this->m_strMsg ); 

return TRUE; 

}  

参考资料:

1.Visual C ++ 网络通信协议分析与应用实现 汪晓平 钟军 人民邮电出版社

2. FTP 协议的分析和扩展 elly http://elly.blogdriver.com/index.jsp

3. RFC中 FTP 相关文档 http://www.ietf.org/rfc/

FTP 协议解析与实现相关推荐

  1. FTP协议解析之Wireshark报文分析

    FTP是客户端-服务器协议,客户端将请求文件,而本地或远程服务器将提供该文件.我们熟知的FTP客户端:WinSCP.WS FTP.FileZilla等都是使用文件传输协议,它是一种标准的Interne ...

  2. FTP协议解析与实现(通过实验讲述FTP协议)

    概述 FTP底层通过TCP实现. FTP采用两个TCP连接,一个作为命令通道(端口号一般是21,用于登陆,删除文件,改变目录操作),一个作为数据通道(用于目录列出,上传下载文件). 以下实验,通过Fi ...

  3. ftp协议是一种用于_______的协议_网络安全常见协议解析:TCP、UDP、HTTP、FTP、SMTP等之间的区别...

    了解网络安全行业的都知道,网络安全协议是营造网络安全环境的基础,是构建安全网络的关键技术.常见的网络协议如HTTP协议.TCP/IP协议.FTP协议等. 如果你想进入网安行业,这些协议都是需要重点要学 ...

  4. java实现FTP协议:wireshark抓包解析

    本节我们看看ftp协议的数据包格式,同时使用代码加以实现.首先我们现在机器上安装ftp服务器,我在自己的机器上安装了QuickFTP Server,它是我随便找来的一款Mac ftp服务器,如下图所示 ...

  5. 马哥教育第二十四ftp协议、vsftpd的高级应用、rpc概念及nfs的基本应用、samba及其基本应用...

    1.ftp协议及vsftpd的基本应用          文件共享服务:                  工作在应用层:ftp(file transfer protocol)             ...

  6. ftp协议是一种用于_______的协议_网工知识角|快速理解FTP和TFTP的区别,实用收藏...

    点上方蓝字关注公众号,坚持每天技术打卡 学网络,就在IE-LAB 国内最著名的高端网络工程师培养基地 FTP和TFTP的区别是什么 CCNA零基础入门必学 FTP(FileTransfer Proto ...

  7. 万维网服务器协议提供web,万维网的HTTP和FTP协议.doc

    万维网的HTTP和FTP协议.doc 万维网的HTTP和FTP协议 摘 要:20世纪40年代以来,人们就梦想能拥有一个世界性的信息库.在这个信息库中,信息不仅能被全球的人们存取,而且能轻松地链接到其他 ...

  8. ftp协议及vsftpd的基本应用

    1.ftp协议及vsftpd的基本应用 vsftpd 是"very secure FTP daemon"的缩写,安全性是它的一个最大的特点.vsftpd 是一个 UNIX 类操作系 ...

  9. TFTP协议解析及C/C++代码实现

    TFTP 用于以非常简单的方式传输文件.与其他文件传输协议(如:FTP 或 HTTP)相比,TFTP 更简单,代码量也更小,因此更易于实现. 通常,TFTP 使用 UDP 作为其传输协议.众所周知的 ...

最新文章

  1. [转]SQL 约束讲解
  2. 使用iOS原生sqlite3框架对sqlite数据库进行操作
  3. plotplayer声道设置原声
  4. python中da_Python中字符的编码与解码
  5. HDU 2818 Building Block
  6. Web页面获取用户控件页面中服务器控件的值
  7. 百度获得国内首批无人驾驶乘用车高速公路道路测试资质
  8. java垃圾回收 分代_Java分代垃圾回收策略原理详解
  9. 几种常用的视频接口(端子)
  10. aliyun托管kubernetes部署postgress
  11. [2018.07.17 T1] 字符串最大值
  12. win8普通版连接远程桌面---RDPWrap
  13. NOR Flash与NAND Flash区别
  14. 用FCM函数实现模糊C均值聚类算法
  15. 计算方法复习提纲-中
  16. 推荐1位AI产品经理求职信息(企业方可要简历),新增3个JD(共计59个、AI PM可内推)...
  17. Android Native Crash崩溃及错误原因分析二-实战解决
  18. 国医馆项目(杂七杂八)
  19. 小草酒店客房管理系统 免费
  20. what this book can do for you ?

热门文章

  1. 一只猴子和那些超神的脚本......
  2. python入门(四)小康小白
  3. clearcase下的一些常用命令
  4. 【大学生软件测试基础】三角形构成问题 - 决策表
  5. TBox、E-Call、B-Call、I-Call是什么?
  6. uniapp 小于1000 按原数字显示 超过1000 数字换算成10w+ 1.3k+ 显示
  7. 程序员如何轻松又愉快的学好英语
  8. ABP VNext学习日记5
  9. 使用Python读取文件夹中的图片
  10. 声源近场与远场定位及方法