读懂源码系列-FileZilla Server 设计原则分析-socket 事件响应流程(3)
来源:互联网 发布:中日韩围棋 知乎 编辑:程序博客网 时间:2024/06/05 23:04
1. 网络模型初探
FTP 服务器会监听指定的 21 端口,等待用户连接,这是所谓的控制连接。当需要数据传输时,客户端和服务器之间会再建立一个数据连接。
本期文章暂不涉及 FTP 协议的处理过程,重点在于梳理 FileZilla Server 的网络模型。
接上一期,FTP 服务器初始化线程代码。该线程创建了 CServer 类,执行流程来到 CServer::Create 函数(节选):
bool CServer::Create(){//Create windowRegisterClassEx(&wndclass);m_hWnd = CreateWindow(_T("FileZilla Server Helper Window"), _T("FileZilla Server Helper Window"), 0, 0, 0, 0, 0, 0, 0, 0, GetModuleHandle(0));if (!m_hWnd)return false;SetWindowLongPtr(m_hWnd, GWLP_USERDATA, (LONG)this);hMainWnd = m_hWnd;//ListenSocketif (CreateListenSocket()) {m_nServerState = STATE_ONLINE;ShowStatus(_T("Server online."), 0);}elseShowStatus(_T("Server not online."), 1);//AdminListenSocketCreateAdminListenSocket();return true;}忽略其他初始化工作,我们来关注监听 socket 的建立,以此探究 FTP 服务器的网络模型。依次跟踪以下代码:
CServer::Create()CServer::CreateListenSocket()CServer::CreateListenSocket(CStdString ports, bool ssl)CAsyncSocketEx::Create(UINT nSocketPort, int nSocketType, long lEvent, LPCTSTR lpszSocketAddress, int nFamily, bool reusable)可以发现其实 CListenSocket 是 CAsyncSocketEx 的派生类。在 CAsyncSocketEx::Create 里,进行了如下工作:
1.创建原始 socket;
2.将原始 socket 存入辅助窗口 CAsyncSocketExHelperWindow;
3.调用 WSAAsyncSelect 将 socket 和辅助窗口关联并指定发生感兴趣的 socket 事件时,使用特定的消息通知窗口关联的过程;
其中第 2 点是最关键的,依次跟踪以下代码,发现每个 socket 关联了一个索引:
CAsyncSocketEx::AttachHandle(SOCKET hSocket, int family)CAsyncSocketExHelperWindow::AddSocket(CAsyncSocketEx *pSocket, int &nSocketIndex)
而第 3 点的巧妙之处在于,为位置为 index 的 socket 指定的消息为 WM_SOCKETEX_NOTIFY + index。因此,每个 socket 都直接对应一条自定义消息,消息分发速度较MFC CAsyncSocket 快(未验证,该项目声称。出处见 AsyncSocketEx.h 文件注释部分)。
此外,CAsyncSocketExHelperWindow 最重要的就是里边的窗口过程。发生 socket 事件时,由辅助窗口的窗口过程处理。发生 FD_ACCEPT 事件时,该窗口过程调用 CAsyncSocketEx::OnAccept(int) 虚函数。 同时,为了保证每个线程只有一个 CAsyncSocketExHelperWindow,在 CAsyncSocketEx 类内有以下两个成员:
//Pointer to the data of the local threadstruct t_AsyncSocketExThreadData{CAsyncSocketExHelperWindow *m_pHelperWindow{};int nInstanceCount{};std::list<CAsyncSocketEx*> layerCloseNotify;} *m_pLocalAsyncSocketExThreadData{};//List of the data structures for all threadsstatic thread_local t_AsyncSocketExThreadData* thread_local_data;
并且,CAsyncSocketEx 类具有以下初始化代码:
bool CAsyncSocketEx::InitAsyncSocketExInstance(){//Check if already initializedif (m_pLocalAsyncSocketExThreadData) {return true;}DWORD id = GetCurrentThreadId();// Get thread specific dataif (!thread_local_data) {thread_local_data = new t_AsyncSocketExThreadData;thread_local_data->m_pHelperWindow = new CAsyncSocketExHelperWindow(thread_local_data);}m_pLocalAsyncSocketExThreadData = thread_local_data;++m_pLocalAsyncSocketExThreadData->nInstanceCount;return true;}因此,这就保证了所有同一个线程里的 CAsyncSocketEx 对象,共享一个 t_AsyncSocketExThreadData 结构体,即共享一个 辅助窗口。
举例来说,bool CServer::Create() 代码里,至少创建了两个 CAsyncSocketEx 对象as1,as2。as1 创建时,由于整个线程还未有 CAsyncSocketEx 对象。因此thread_local_data = 0,新建了辅助窗口。而 as2 创建时,thread_local_data != 0,此时实例数量为2。整体图解如下:
2.总结
通过忽略具体的处理流程,我们找到了 socket 事件的响应流程。那么具体如何处理 socket 时间呢,这就涉及到具体的执行线程了。将由下一节讲述。本章有意思的地方有:
1.通过 static thread_local 关键字设计同一线程内所有对象共享的数据
2.通过索引加快消息分发
阅读全文
0 0
- 读懂源码系列-FileZilla Server 设计原则分析-socket 事件响应流程(3)
- 读懂源码系列-FileZilla Server 设计原则分析-socket 事件处理流程(4)
- 读懂源码系列-FileZilla Server 设计原则分析-入口分析(2)
- 读懂源码系列-FileZilla Server 设计原则分析-编译篇(1)
- FileZilla Server源码分析(1)
- FileZilla Server源码分析--大漠落日5节
- Service源码分析系列(二):bindService流程分析
- Netty源码分析(九)—IO事件处理流程
- libevent源码学习-----事件驱动流程分析
- tornado源码分析系列(四)[buffer事件类IOStream]
- springmvc源码分析系列-请求处理流程
- Filezilla Server教程(图)
- [FileZilla Client 源码分析二]CCommandQueue类
- FileZilla Server
- jQuery-1.9.1源码分析系列(十六)ajax——响应数据处理和api整理
- bootstrap源码分析系列:二,栅格和响应式布局
- 功能强大的IOCP Socket Server模块源码——完成端口通讯服务器(IOCP Socket Server)设计(六)
- 功能强大的IOCP Socket Server模块源码——完成端口通讯服务器(IOCP Socket Server)设计(六)
- 欢迎使用CSDN-markdown编辑器
- Java常用算法——冒泡排序
- 100. Same Tree
- 9.6(周三)
- iOS10 本地通知
- 读懂源码系列-FileZilla Server 设计原则分析-socket 事件响应流程(3)
- Codeforces 854 B Maxim Buys an Apartment
- 关于热设计-以LDO 7805为例
- UnityShader从入门到放弃(五)漫反射—逐片元光照
- 简易贪食蛇-C语言实现
- 对象的查询和设置(JS高级)
- extern作用详解
- 排序-1-冒泡排序
- HDU 1711 Number Sequence