FTP编程与资源访问.ppt_第1页
FTP编程与资源访问.ppt_第2页
FTP编程与资源访问.ppt_第3页
FTP编程与资源访问.ppt_第4页
FTP编程与资源访问.ppt_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章 FTP编程与资源访问,FTP应用基础,制作FTP上传下载器,FTP服务器的实现,自制FTP客户端与服务器对接,6 . 1 FTP应用基础,6.1.1 FTP简介 与大多数Internet应用一样,FTP也是基于客户端服务器(C/S)模式工作的,如图6.1所示。,6.1.2 FTP的特性,1适应异构系统 FTP可以使用的文件类型有以下四种。 (1)ASCII码文件。 这是FTP默认的文本文件格式,数据在传输过程中使用与Telnet相同的NVT ASCII码。 (2)EBCDIC码文件。 它也是一种文本类型文件,只是利用8位代码表示一个字符,该文本文件在传输时要求两端都使用EBCDIC码。 (3)图像(Image)文件。 图像文件也称为二进制文件类型,发送的数据为连续的比特流,实际传输时,发送方将数据打包成为8位,然后以字节为单位进行传输。 (4)本地(local)文件。 字节的大小由本地主机定义,即每一字节的比特数由发送方规定,用于在具有不同字节大小的主机间传输二进制文件。,6.1.2 FTP的特性,FTP支持的文件数据结构有如下几种结构。 (1)文件结构。这是FTP默认的方式,文件被认为是一个连续的字节流,不存在内部的结构。 (2)记录结构。只适用于文本文件(ASCII或EBCDIC),是由连续的记录构成的。 (3)页结构。当文件是由非连续的多个部分组成时,使用页结构,这种文件称为随机访问文件。每页都带有页号发送,以便接收方能够随机地存储各页。,6.1.2 FTP的特性,2匿名FTP 通常,使用FTP时必须首先登录,输入用户名和密码,从远程主机获得相应的权限后,方可下载或上传文件。但这违背了Internet的开放性,匿名FTP就是为解决这个问题而产生的一种机制:用户可通过它连接到远程主机并下载文件,而无须成为其注册用户。系统管理员建立一个特殊的用户名anonymous,Internet上的任何人在任何地方都可使用该用户名。,6.1.3 FTP工作原理,下面以客户要从FTP服务器上下载一个文件为例,说明FTP的完整工作过程。其工作原理如图6.2所示。,6.1.3 FTP工作原理,1启动FTP 用户通过GUI界面操作客户端软件,执行启动FTP的用户交互式命令。 2建立控制连接 客户端TCP层根据用户命令中给出的服务器IP地址,向服务器提供FTP服务的21端口发出主动建立连接的请求。服务器收到请求后,通过三次握手,在进行FTP命令处理的用户协议解释器进程和服务器协议解释器进程之间建立一条TCP连接,6.1.3 FTP工作原理,3建立数据连接和进行文件传输 (1)在客户端请求分配一个临时的TCP端口号。 (2)在客户端由客户协议解释器通过控制连接,向服务器协议解释器发送两条命令:一条命令(使用PORT命令)是将客户端的IP地址和申请到的临时端口号这两个参数,告诉给服务器协议解释器;另一条命令是将服务器上某文件传输到客户端的服务请求。 (3)服务器协议解释器收到客户端的IP地址和临时端口号后,以该IP地址和端口号为目标,使用服务器的20端口(TCP层用于传输数据的端口)向客户发出主动建立连接的请求。 (4)客户收到请求后,通过三次握手,在客户数据传输进程和服务器数据传输进程之间建立一条TCP连接,下面的传输文件就通过这个连接进行,由于它的建立是专用于传输数据的,所以将它称为数据连接。 (5)服务器的数据传输进程从它的文件系统中找到客户进程请求传输的文件。 (6)服务器的数据传输进程通过数据连接将该文件发送到用户数据传输进程。 (7)用户数据传输进程将该文件交给客户端文件系统进行存储。 (8)文件传输完成后,由服务器主动关闭该数据连接。,6.1.3 FTP工作原理,4关闭FTP 除了本例中介绍的客户从FTP服务器下载一个文件时要建立数据连接外,当客户要向服务器上传一个文件或客户要求查看服务器文件列表时,也要建立相应的数据连接。因此,在下列三种情况下都需要在客户和服务器之间自动建立数据连接。 从客户向服务器发送一个文件。 从服务器向客户发送一个文件。 从服务器向客户发送文件目录列表。,6.1.3 FTP工作原理,其实客户端可以不对服务器通知数据连接的端口,在这种情况下,服务器同样可以与客户端建立一条数据连接,只不过在客户端,数据连接就使用与控制连接相同的端口号。这时,控制连接和数据连接可以分别表示如下。 控制连接: 数据连接: ,6.1.4 FTP命令和应答,1FTP命令 FTP命令都是由三个或四个大写ASCII码字符组成的,表6.1列出了FTP命令,共分为三大类。 2FTP应答 (1)服务器为了对数据传输的请求和过程进行同步,这是TCP所要求的,TCP要求对接收到的数据都要进行确认。 (2)为了使用户了解服务器的状态,用户可以根据收到的状态信息对服务器是否正常执行了有关操作进行判断。,6.1.4 FTP命令和应答,三位数字每位都有特定的意义,详细内容见表6.2。,6.1.5 FTP网络环境搭建和使用,1安装FTP服务组件 FTP服务组件不是Windows操作系统默认安装的,当需要使用时要由用户补装添加这个组件。选择菜单命令“开始”“控制面板”,双击“添加或删除程序”项,在弹出的对话框左侧单击“添加/删除Windows组件”选项,如图6.3所示。,6.1.5 FTP网络环境搭建和使用,在弹出的“Windows组件向导”对话框中勾选“Internet 信息服务”复选框,单击“详细信息”按钮,如图6.4所示。,6.1.5 FTP网络环境搭建和使用,在弹出的“Internet信息服务(IIS)”对话框中找到“文件传输协议(FTP)服务”项并勾选。然后连续单击“确定”按钮,直至回到如图6.5所示的界面。,6.1.5 FTP网络环境搭建和使用,找到安装操作系统时使用的Windows系统安装盘,放入光驱后单击“确定”按钮,如图6.6所示,系统将自动启动安装过程。,6.1.5 FTP网络环境搭建和使用,2配置FTP站点 选择菜单命令“开始”“控制面板”“性能和维护”“管理工具”“Internet信息服务”,打开如图6.7所示的“Internet 信息服务”窗口。,6.1.5 FTP网络环境搭建和使用,为了以后测试FTP程序向服务器上传(删除)文件等“写入”类功能,必须同时开放FTP服务器的读和写权限,右击“默认FTP站点”“属性”,在如图6.8所示的“默认 FTP 站点 属性”对话框中选择“主目录”选项卡。,6.1.5 FTP网络环境搭建和使用,最后,将FTP站点的“写入”权限也一并开放,操作如图6.9所示。,6.1.5 FTP网络环境搭建和使用,3测试FTP站点 FlashFXP是一款功能强大的FTP客户端软件,拥有庞大的用户群和丰富的种子资源,其主界面如图6.10所示。,6.1.5 FTP网络环境搭建和使用,选择菜单命令“会话”“快速连接”,在如图6.11所示的“快速连接”对话框的“地址或URL”栏中输入“”(本地计算机环回测试地址),端口保持默认“21”,匿名登录,单击“连接”按钮。,6.1.5 FTP网络环境搭建和使用,右击本地目录下的文档“我的简历.doc”“传输”,如图6.12所示,文件被上传到FTP根目录下。,6 . 2 制作FTP上传下载器,6.2.1 WinInet类对FTP的支持 FTP客户端编程也是主要以MFC WinInet为支撑的。WinInet提供了如图6.13所示的Internet会话类CInternetSession、连接类CInternetConnection、文件类CInternetFile、文件操作类CFileFind,以及通用异常类CInternetException等。,6.2.2 设计软件界面,工程创建好后,设计软件界面如图6.14所示。,6.2.2 设计软件界面,与界面各元素关联的变量见表6.3。,6.2.3 编程实现,为了能在编程中使用WinInet类的功能,需要在SelfFtpUpDownloaderDlg.h中包含头文件: #include “afxinet.h“ 勾选“匿名”复选框将触发OnNoname方法,代码所示。,6.2.3 编程实现,“连接”按钮的事件过程,代码如下: void CSelfFtpUpDownloaderDlg:OnConnect() this-ConnectFtp(); /连接FTP服务器 this-UpdateDir(); /显示服务器上的目录和文件夹列表 /以下为界面控制 ServerIP.EnableWindow(false); m_port.EnableWindow(false); m_connect.EnableWindow(false); m_disconnect.EnableWindow(true); m_enterdir.EnableWindow(true); m_upload.EnableWindow(true); m_download.EnableWindow(true); m_delete.EnableWindow(true); m_noname.EnableWindow(false); m_exit.EnableWindow(false); ,6.2.3 编程实现,这个事件过程用到两个函数:ConnectFtp()和UpdateDir()。 ConnectFtp()函数代码。 FTP客户程序要建立与服务器的连接,需要一个CInternetSession和CFtpConnection 对象,但并不需要直接创建CFtpConnection对象,而是通过调用CInternetSession: GetFtpConnection实现。 UpdateDir()函数代码。,6.2.3 编程实现,为保证连接的顺利成功,需要在 SelfFtpUpDownloaderDlg.h的对话框类定义中添加CInternetSession类对象指针pInternetSession和CFtpConnection对象指针pFtpConnection的定义,还要定义指示连接成功与否的变量bconnect,另外声明上述两个函数的原型: BOOL bconnect; CInternetSession *pInternetSession; CFtpConnection *pFtpConnection; void ConnectFtp(); void UpdateDir();,6.2.3 编程实现,“进入”按钮使得用户可以进入自己选中的目录文件夹,其事件代码如下: void CSelfFtpUpDownloaderDlg:OnEnterDir() CString selfile; m_lst.GetText(m_lst.GetCurSel(),selfile); /获取用户选择的目录名 if (!selfile.IsEmpty() pInternetSession-Close(); /及时关闭废弃的会话句柄 this-ConnectFtp(); /重新连接,保持与服务器的持续会话 CString strdir; pFtpConnection-GetCurrentDirectory(strdir); /获得原来的工作目录 strdir += selfile; /生成新目录 pFtpConnection-SetCurrentDirectory(strdir); /改变目录到当前服务目录 this-UpdateDir(); /更新目录列表 m_goback.EnableWindow(true); ,6.2.3 编程实现,为使用户灵活地切换目录,程序必须提供目录返回功能,使用户能够返回上一级目录,“返回”按钮的事件过程代码如下: void CSelfFtpUpDownloaderDlg:OnGoBack() CString strdir; pFtpConnection-GetCurrentDirectory(strdir); int pos; pos = strdir.ReverseFind(/); /用字符串截取的方式获得上级目录 strdir = strdir.Left(pos); pInternetSession-Close(); /关闭废弃的会话 this-ConnectFtp(); /重新连接,保持持续会话 pFtpConnection-SetCurrentDirectory(strdir); this-UpdateDir(); /更新目录列表 ,6.2.3 编程实现,本例实现了用户对FTP资源的上传、下载和删除这三项最基本的操作。 “上传”按钮的事件过程代码。 “下载”按钮的事件过程代码。 “删除”按钮的事件过程代码。,6.2.3 编程实现,当用户访问完毕,单击“断开”按钮退出登录,其事件过程代码如下: void CSelfFtpUpDownloaderDlg:OnDisconnect() pInternetSession-Close(); /结束会话 m_lst.ResetContent(); m_lst.AddString(“连接已断开!“); /界面控制 ServerIP.EnableWindow(true); m_port.EnableWindow(true); m_connect.EnableWindow(true); m_disconnect.EnableWindow(false); m_enterdir.EnableWindow(false); m_goback.EnableWindow(false); m_upload.EnableWindow(false); m_download.EnableWindow(false); m_delete.EnableWindow(false); m_noname.EnableWindow(true); m_exit.EnableWindow(true); ,6.2.3 编程实现,为了使整个程序功能完善,在客户端刚启动,用户尚未登录时,也需要进行一些初始化工作,告诉用户“目前尚未登录!”,初始化代码如下: bconnect = false; m_lst.ResetContent(); m_lst.AddString(“尚未连接服务器,无法浏览FTP资源!“); m_connect.EnableWindow(false); m_disconnect.EnableWindow(false); m_enterdir.EnableWindow(false); m_goback.EnableWindow(false); m_upload.EnableWindow(false); m_download.EnableWindow(false); m_delete.EnableWindow(false);,6.2.4 测试FTP客户端,将之前已经上传到C:Inetpubftproot下的Word文档删除,启动FTP上传下载器SelfFtpUpDownloader,如图6.15所示在IP地址栏中输入“”,端口号填21,勾选“匿名”复选框,单击“连接”按钮访问本机上的FTP服务器。,6.2.4 测试FTP客户端,单击“上传”按钮,弹出“打开”对话框,进入如图6.16所示的“我的文档”目录,选中“我的简历.doc”文档,单击“打开”按钮。,6.2.4 测试FTP客户端,文件上传到服务器,显示“上传成功!”消息框,如图6.17所示。,6 . 3 FTP服务器的实现,6.3.1 项目框架的建立 首先创建VC项目工程,工程命名为ftpSrver(“基于FTP协议的服务器”之意)。设计程序界面如图6.18所示。,6.3.1 项目框架的建立,由于服务器提供了对已注册用户信息进行编辑,以及添加和删除用户的功能,所以需要另外设计一个对话框专用于设置用户信息。向工程中添加MFC类CAccountDlg,并设计对话框界面,如图6.19所示。,6.3.1 项目框架的建立,为GUI界面上的各控件关联变量,见表6.4和表6.5所示。,在ftpSrverDlg.h中添加定义。,6.3.1 项目框架的建立,在项目中添加类CServer和结构体CAccount(如图6.20所示)。,6.3.1 项目框架的建立,在Server.h中,定义本程序将要使用的宏、结构体和类。 在ftpSrverDlg.h中包含头文件: #include “stdlib.h“ #include “Server.h“ 同时在类CftpSrverDlg中定义: public: AccountArray m_AccountArray; CServer m_server; 在ftpSrverDlg.cpp中包含头文件: #include “AccountDlg.h“ #include ,6.3.1 项目框架的建立,同时在BOOL CftpSrverDlg:OnInitDialog()中添加初始化代码: /初始化时,为服务器添加几个固定用户 CAccount fixAccount; fixAccount.username = “admin“; /管理员 fixAccount.password = “admin“; fixAccount.directory = “C:“; m_AccountArray.Add( fixAccount ); CLISTACCOUNT.AddString(fixAccount.username); fixAccount.username = “usr“; /普通用户 fixAccount.password = “usr“; fixAccount.directory = “D:“; m_AccountArray.Add( fixAccount ); CLISTACCOUNT.AddString(fixAccount.username); fixAccount.username = “anonymous“; /匿名用户 fixAccount.password = “; fixAccount.directory = “C:Documents and SettingsAll UsersDocuments“; m_AccountArray.Add( fixAccount ); CLISTACCOUNT.AddString(fixAccount.username);,6.3.1 项目框架的建立,在初始化时,预先在服务器上注册了三个默认的用户账户:管理员、普通用户和匿名用户。它们的用户名、密码和默认根目录见表6.6。,6.3.1 项目框架的建立,在Server.cpp中定义: #include “ftpSrver.h“ /*/ /* global data*/ /*/ DWORD g_dwTotalEventAmount = 0; /总事件数 DWORD g_index; WSAEVENT g_EventArrayWSA_MAXIMUM_WAIT_EVENTS; /手动重置对象 LPSOCKET_INF g_SocketArrayWSA_MAXIMUM_WAIT_EVENTS; /新SOCKET_INF结构 CRITICAL_SECTION g_CriticalSection; /临界区 /处理线程函数声明 UINT ProcessThreadIO( LPVOID lpParam );,6.3.2 FTP服务器界面总控,“启动服务”按钮事件过程代码。 “停止服务”按钮的事件过程代码如下: void CftpSrverDlg:OnStopServer() m_server.m_bStopServer = true; closesocket(m_server.sDialog); closesocket(m_server.sListen); CLISTSERVERINFO.AddString(“服务已停止!“); ServerIP.EnableWindow(true); CEDITPORT.EnableWindow(true); 停止服务时需要先后将会话Socket和监听Socket都关闭。程序中使用BOOL型变量m_bStopServer来指示服务的开关状态,这个变量是服务类CServer的成员变量,在Server.cpp的CServer构造方法中赋初值,代码如下: CServer:CServer(void) m_bStopServer = FALSE; CServer:CServer(void) ,6.3.2 FTP服务器界面总控,“编辑”按钮的事件过程代码。 “添加用户”按钮的事件过程代码。 “删除用户”按钮的事件过程代码。,6.3.3 FTP服务流程的实现,ServerConfigInfo()方法代码如下: /服务器配置 void CServer:ServerConfigInfo( AccountArray* accountArray,BYTE nFild,UINT port) /账户设置 int size = (int)(*accountArray).GetCount(); for( int i = 0 ; i size ; i + ) m_RegisteredAccount.Add( (*accountArray)i ); /IP设置 for( int i = 0;i 4;i +) IpFildi = nFildi; /端口设置 m_ServerPort = port; /设置服务器开启状态 m_bStopServer = FALSE; ,6.3.3 FTP服务流程的实现,之后的程序代码都属于FTP服务本身的实现代码,自然都位于源文件Server.cpp中。服务对应的主线程为ServerThread。 主线程ServerThread代码。 这些错误提示消息都用WSAGetLastError()函数截获,存储在一个字符数组errorMsg中,通过弹出对话框显示出来,使用的程序代码形式上都完全一样,只是显示错误信息的文本内容不同,分别列于表6.7。,6.3.3 FTP服务流程的实现,顺便给出服务器回传欢迎消息的SendWelcomeMsg()方法的代码: /发送欢迎消息 BOOL CServer:SendWelcomeMsg( SOCKET s ) char* welcomeInfo = “220 Server readyrn“; if( send( s, welcomeInfo, (int)strlen(welcomeInfo), 0 )=SOCKET_ERROR ) AfxMessageBox(_T(“Failed in sending welcome msg. POS:CServer:SendWelcomeMsg“); return FALSE; return TRUE; ,6.3.3 FTP服务流程的实现,工作者线程ProcessThreadIO代码。 工作者线程接收数据时采用RecvRequest()方法。 RecvRequest()方法代码。,6.3.4 FTP协议的实现,Login()方法代码。 这里,服务器对接收到的客户端发来的信息按协议规范进行处理。 通用的处理形式如下: strstr( strupr(socketInfo-buffRecv),“XXX“ )|strstr( strlwr(socketInfo-buffRecv),“xxx“) DealWithCommand()方法代码。,6.3.5 FTP实现辅助代码,1)网络连接管理类 AcceptConnectRequest()(接收连接请求)代码如下: SOCKET CServer:AcceptConnectRequest(SOCKET DataConnect()(建立数据连接)代码。 上段代码中用到了GetLocalAddress()函数,用于获取本地IP地址,其实现。,6.3.5 FTP实现辅助代码,2)数据收发类 本程序将数据接收和发送的操作分别封装在DataSend()和DataRecv()函数中,以便协议实现过程中随时调用。 DataSend()函数代码。 DataRecv()函数代码。 对于服务器向客户端返回应答的操作也封装成SendACK()函数。 SendACK()函数代码。,6.3.5 FTP实现辅助代码,3)格式处理类 DivideRequest()函数(分离请求信息),代码如下: void CServer:DivideRequest(char *request, char *command, char *cmdtail) int i = 0; int len = (int)strlen( request ); command0 = 0; for( i=0 ; ilen ,6.3.5 FTP实现辅助代码,CombindFileNameSize()函数(把文件名及文件大小信息整合到一起),代码如下: /整合后的信息保存到filenamesize中并返回文件的大小 int CServer:CombindFileNameSize(const char *filename, char *filnamesize) /假定文件的大小不超过4GB,只处理低位 int fileSize = -1; FILE_INF fileInfo1; /获取文件列表信息,并保存至fileInfo中,fileAmount记录文件数目 int fileAmount = GetFileList( fileInfo,1,filename ); if( fileAmount != 1 ) return -1; /把文件名和大小信息整合到一起 sprintf( filnamesize, “%s“,filename,fileInfo0.nFileSizeLow ); /获得文件大小 fileSize = fileInfo0.nFileSizeLow; /返回文件大小 return fileSize; ,6.3.5 FTP实现辅助代码,上面程序中的GetFileList()函数用于获取文件列表,代码所示。 FileListToString()函数(将文件列表信息转换成字符串),代码所示。 ConvertCommaAddrToDotAddr()函数(将逗号分隔的IP序列转化为点分十进制形式),代码所示。 ConvertDotAddrToCommaAddr()函数可将一个32位Internet主机地址和一个16位TCP端口地址转换为一个由6个被逗号隔开的数字组成的IP地址序列。 ConvertDotAddrToCommaAddr()函数代码。,6.3.5 FTP实现辅助代码,NetToHost()函数(将/格式转换为格式),代码如下: void CServer:NetToHost(char *path) int index = 0; while( pathindex ) if( pathindex = / ) pathindex = ; index+; ,6.3.5 FTP实现辅助代码,HostToNet()函数(将格式转换为/格式),代码如下: void CServer:HostToNet(char *path) int index = 0; while( pathindex ) if( pathindex = ) pathindex = /; index+; ,6.3.5 FTP实现辅助代码,4)目录操作类 GetAbsoluteDirectory()函数(获得绝对路径),代码所示。 上面程序中用到了格式处理的NetToHost()函数。 IsPathExist()函数(检测路径是否合法),代码如下: BOOL CServer:IsPathExist(char *path) if( GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES | GetLastError() != ERROR_FILE_NOT_FOUND ) return TRUE; return FALSE; ,6.3.5 FTP实现辅助代码,GetRalativeDirectory()函数(获得相对路径),代码如下: void CServer:GetRalativeDirectory(char *currDir,char*rootDir,char* ralaDir) int nStrLen = (int)strlen( rootDir ); /比较字符串currDir和rootDir的前nStrLen个字符但不区分大小写 if( strnicmp( currDir,rootDir, nStrLen ) = 0 ) strcpy( ralaDir,currDir + nStrLen ); /判断是否是根目录 if( ralaDir != NULL ,6.3.5 FTP实现辅助代码,5)文件操作类 ReadFileToBuffer()函数(将指定文件写入缓存),代码所示。 TryDeleteFile()函数(删除文件),代码如下: int CServer:TryDeleteFile(char *deletedPath) /定义一个CFileFind类对象用于查找 CFileFind fileFinder; if( !fileFinder.FindFile( deletedPath ) ) /-路径不合法 return CANNOT_FIND; else if( DeleteFile( deletedPath ) ) /-文件能删除 return DIR

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论