FileZilla客户端实现分析
- 格式:pdf
- 大小:380.49 KB
- 文档页数:7
FileZilla客户端实现分析FileZilla Client AnalysisBy David.Zhu 2005/8/2 Content List:•Source File Classification•Main Framework of FileZilla Client•Network Implementation Analysis•Get Nuggets from Misc•Explore FileZilla Client GUI•Knowledge Repository•Summarize•Reference1.1 Source File ClassificationKernel CommandQueue.cpp FileZilla.cpp FileZillaApi.cpp FtpListResult.cpp MainThread.cpp SiteManager.cppDefinition &ConfigurationSFtpCommandIDs.h FzApiStructures.h structures.hNetwork Substrate AsyncSocketEx.cpp AsyncGssSocketLayer.cpp AsyncProxySocketLayer.cpp AsyncSocketExLayer.cpp AsyncSslSocketLayer.cpp ControlSocket.cpp IdentServerControl.cpp IdentServerDataSocket.cpp SftpControlSocket.cpp FtpControlSocket.cpp TransferSocket.cppMisc AsyncRequestQueue.cpp FileChangeNotify.cpp MFC64bitFix.cpp PathFunctions.cpp version.cpp ApiLog.cpp ServerPath.cpp SFtpIpc.cpp SpeedLimit.cpp DirectoryCache.cpp Crypt.cppGUI Related All others .They are too many and I don't wanna list them here.1.2 Main Framework of FileZilla ClientFileZilla 客户端的GUI核心就是CMainFrame,CMainFrame在创建的时候(CMainFrame::OnCreate)会创建一个 CFileZillaApi对象(m_pFileZillaApi)和一个CCommandQueue对象 (m_pCommandQueue),FileZilla客户端为其命令通道专门创建了一线程CMainThread, 该线程采用Command模式来实现的:GUI 部分通过PostThreadMessage发送FZAPI_THREADMSG_COMMAND消息给CMainThread来完成发送FTP命令,CMainThread将所有的FTP命令封装成一个t_command结构(defined in FileZillaApi.h),通过FZAPI_THREADMSG_COMMAND线程消息来接收GUI发来的FTP命令。
CFileZillaApi则在GUI和 CMainFrame 中充当了一个Proxy的作用,而CCommandQueue则充当着命令缓冲和序列化的作用。
在CMainThread中保存了主窗口的HWND和消息ID,在必要的时候CMainThread就可以通过窗口的消息机制来通知主窗口线程。
我 们知道在FTP的时候都是走的双通道:一个命令通道;一个数据通道。
在FileZilla中命令通道对应的就是CFtpControlSocket,数据 通道对应的就是CTransferSocket.在CMainThread初始化的时候(CMainThread::InitInstance),就创建 了CFtpControlSocket,在GUI发命令要求连接FTP服务器的时候,其调用 Connect去连接远程FTP服务器。
数据传输通道的建立则是在通过命令通道发送了LIST命令,FTP服务器返回之后,才创建了 CTransferSocket对象,并将其作为一个Server,调用Listen等待FTP服务器的连接。
数据通道主要是接收LIST命令返回的服务 器文件树和DOWNLOAD命令传来的下载文件的数据(见CTransferSocket::OnReceive)。
FileZilla客户端提供了KeepAlive机制,在CMainThread中设置了一个Timer,如果配置了OPTION_KEEPALIVE选项,系统就会在空闲时向服务器随机的发送PWD,REST 0 ,TYPE A ,TYPE I 命令,以避免FTP服务器因为客户端连上来后长时间没有动作而自动关闭与客户端的连接。
1.3 Network Implementation AnalysisFileZilla的网络部分的结构图如下:其 中CAsyncSocketEx是对MFC的CAsyncSocket的改进,据说比CAysncSocket性能上要高一点。
在 CAsyncSocketEx中添加了对CAsyncSocketLayer的支持,各个SocketLayer 链接成一个双向的链表(见CAsyncSocketExLayer::m_pNextLayer和 CAsyncSocketExLayer::m_pPrevLayer),在CAsyncSocketEx 中记录了这个链表的头尾指针。
对 FileZilla来说网络就是其核心,而FillaZilla的网络部分主要就是CAsyncSocketEx和 CAsyncSocketExLayer了,下面我们来分析一下CAsyncSocketEx和CAsyncSocketExLayer的工作机制。
首 先讲讲CAsyncSocketEx,其实在MFC里面有一个对基于HWND的异步事件的Winsock管理模型的封装类CAsyncSocket,但作 者Tim Kosse这里又重新了一个CAsyncSocketEx类提供了跟MFC的CAsyncSocket相同的接口方法和功能,在eMule开源项目中我发 现其网络部分也是用的这个FileZilla中的CAsyncSocketEx。
那么CAsyncSocketEx比CAsyncSocket好,好在哪 里呢?Tim Kosse在解释为什么CAsyncSocketEx比MFC的CAsyncSocket快时说:"每 个使用CAsyncSocket的线程都会创建一个window,CAsyncSocket就是使用这个窗口的句柄来调用WSAAsyncSelect 的,直到这里CAsyncSocketEx和CAsyncSocket都是一样的,但是对一个线程中的所有Socket,CAsyncSocket仅仅使 用一个消息WM_SOCKET_NOTIFY,其wParam是套接字的句柄,而window通过一个内部建立好的map,根据这个套接字的句柄来获取 CAsyncSocket的Instance.而CAsyncSocketEx就不同了,它使用了从WM_USER到0xBFFF的消息来为每个 Socket提供一个通知消息,这样window在接受到一个消息后,将 index of message - WM_USER作为内部数组的Index来获取CAsyncSocketEx的Instance.所以CAsyncSocketEx就要比 CAsyncSocket快一些,特别是在管理大量的Socket的时候,性能的提升还是比较明显的。
".另外,CAsyncSocketEx还提供了a flexible layer system和套接字的状态机实现。
接下来我们来分析一下CAsyncSocketEx的Layer系统是如何工作的.从 上图我们可以看到,CAsyncSocketEx将Receive,Send,Close,Connect,Create,Listen,Accept,ShutDown,GetPeerName,GetSockName 这些调用按照左边的顺序一层一层的往下抛,一直到最后一个Layer才真正调用相应的API函数。
同时,Helper窗口函数在收到通过 WSAASyncSelect机制发过来的事件时,首先将其发给最下面一层处理,然后按照上图右边的顺序,从下往上通过 OnReceive,OnClose,OnAccept,OnConnect,OnSend 一层一层的调用。
同 时,CAysncSocketLayer还使用WM_USER消息将其内部错误反馈给CAsyncSocketEx(通过 TriggerEvent,PostMessage到HelperWindow);在CAysncSocketLayer和CAsyncSocketEx 之间还有一个Callback机制,CAsyncSocketExLayer::DoLayerCallback把消息封装成 t_callbackMsg,调用CAsyncSocketEx::AddCallbackNotification添加到CAsyncSocketEx 的内部队列m_pendingCallbacks中等待处理。
我感觉对CAsyncSocketLayer的机制还不是很清晰,下面 再进一步分析一个Layer的实现吧.在FileZilla中已经实现了三个Layer了:ProxyLayer,sFtp Layer和SSL Layer.下面找个最简单的分析一下啦,就看Proxy Layer吧:) CAsyncProxySocketLayer主要是提供了对SOCKSv4,SOCKSv5和HTTP1.1 代理的支持。
通过其源代码的分析,其也主要是在Connect和GetHostByName这两个部分做了一些处理,使得在连接应用服务器之前先连接上代 理服务器,并对客户端进行认证,在代理服务器上建立circuits .其他的就没什么了。
在 CAsyncSocketLayer的实现中,可以看到其主要还是利用SendNext,ReceiveNext,XXXXNext方法来处理数据,而不 是在末尾调用CAsyncSocketLayer基类的同样方法。
在发现错误的时候通过调用TriggerEvent和DoLayerCallback来 向上层报告相关的网络错误。
1.4 Get Nuggets from Misc 多语言支持FileZilla客户端的多语言支持采取的是资源DLL的形式,每种Language都被编译成一个独立的DLL,这个DLL中包含了FileZilla的所有Dialog,Menu,String Table,Toolbar,Version,Accelarator资源。