网狐棋牌代码分析(四)TimerEngined定时器分析6

标签:游戏玩法    日期:2017-08-05 18:32    录入:汇盛国际平台    浏览:

相关UML:

网络引擎整体结构:

网狐棋牌代码分析(五)_TCPSocketEnging分析

SocketItem细节:

网狐棋牌代码分析(五)_TCPSocketEnging分析

先来看几个底层结构:

//重叠结构类

classCOverLapped

{

//变量定义

public:

WSABUFm_WSABuffer;//数据指针

OVERLAPPEDm_OverLapped;//重叠结构

constenOperationTypem_OperationType;//操作类型

//函数定义

public:

//构造函数

COverLapped(enOperationTypeOperationType);

//析构函数

virtual~COverLapped();

//信息函数

public:

//获取类型

enOperationTypeGetOperationType(){returnm_OperationType;}

};

//接收重叠结构

classCOverLappedSend:publicCOverLapped

{

//数据变量

public:

BYTEm_cbBuffer[SOCKET_BUFFER];//数据缓冲

//函数定义

public:

//构造函数

COverLappedSend();

//析构函数

virtual~COverLappedSend();

};

//重叠结构模板

templateclassCATLOverLapped:publicCOverLapped

{

//函数定义

public:

//构造函数

CATLOverLapped():COverLapped(OperationType){}

//析构函数

virtual~CATLOverLapped(){}

};

先复习下基础,Windows下的网络模型有很多种,这里只拿出三种来说:

EventSelect:基于信号机制,以socket为单位绑定信号量,当socket上有指定的事件发生时激发信号,然后查询事件处理事件重设事件,继续在信号量上等待。其实也是在伯克利select模型上的换不换药的加强。

OverLapped:分两种工作模式完成回调,和完成事件。重叠IO监视每次操作,每次IO都绑定一个重叠对象,当操作完成以后激发信号或者调用回调。

IOCP:和overlapped类似,不过结果经过了Windows的预处理以队列的形式挂在完成端口上

根据上面的复习,可以得出一个结论,IOCP环境中每一次IO操作都需要一个重叠结构,那么一个CServerSocketItem至少需要如些这些东东:

他要接受数据,所以必须有一个接受数据的OverLapped

它要发送数据,说以必须有一个发送数据的OverLapped

netFox对OverLapped做了使用了类似池的的管理手段,他的Send都是不等待上一次完成就直接投递下一个请求了,,,这是很操蛋的做法,,,

然后继续复习下基础:

在EventSelect模型中获处理件类型流程是这样:

event受信,使用::WSAEnumNetworkEvents查询和这个event关联的socket发生的事件,根据查询到的事件类型去处理事件

在以每一次IO为查询对象重叠IO、IOCP模型中是这样:

使用GetOverlappedResult或者GetQueuedCompletionStatus然后根据重叠结构去查询投递的是什么类型的操作,然后找到关联的socket去操作,,,

这样必然要给OverLapped做个扩展,提供一种通过OverLapped查询操作类型和socket的能力。

通过分析代码,netFox关联socket是通过在创建完成端口的时候绑定SocketItem对象指针完成的,操作类型是通过对OverLapped结构加强完成的。

通过GetQueuedCompletionStatus获取到完成OverLapped以后使用一个宏:

(这是COverLapped类型)pSocketLapped=CONTAINING_RECORD(pOverLapped,COverLapped,m_OverLapped);

来获取包装后的OverLapped,然后获取操作类型,然后执行具体操作。

其实宏的展开如下:

(COverLapped*)((BYTE*)pOverLapped-(COverLapped*)(0)->m_OverLapped);

pOverLapped是获取到的某个COverLapped中的成员变量,(COverLapped*)(0)->m_OverLapped是到在COverLapped中的偏移,((BYTE*)pOverLapped-(COverLapped*)(0)->m_OverLapped)就是根据pOverLapped推算出来的包含地址为pOverLapped作为成员变量m_OverLapped的COverLapped对象的地址。

然后就分别调用:

//发送完成函数

boolCServerSocketItem::OnSendCompleted(COverLappedSend*pOverLappedSend,DWORDdwThancferred);

//接收完成函数

boolCServerSocketItem::OnRecvCompleted(COverLappedRecv*pOverLappedRecv,DWORDdwThancferred);

为毛要区分SendOverLapped和RecvOverLapped呢,,,

应为投递一次Send不一定是瞬间完成的,在处理的过程中存储数据的内存应该是锁定的,也就是不允许修改的,,,所以OverLapped应该自己管理内存。

而recv应该也是需要有一片内存直接接受数据的,很奇怪netFox没有提供,,,

recv居然是在投递接受请求的时候给了一个空的buffer,然后在完成回调中自己再次调用recv方法接受数据。

★★★小编:汇盛国际注册 整理文章,欢迎大家转载 ★★★
上一篇:互联网SEO优化
下一篇:没有了