查看: 326|回复: 1

网狐棋牌(五) TCPSocketEnging分析(2)

[复制链接]

8

主题

37

帖子

224

积分

vip会员

Rank: 1

积分
224
发表于 2020-3-27 16:16:17 | 显示全部楼层 |阅读模式
根据上面的复习,可以得出一个结论,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对象的地址。
然后就分别调用:

//发送完成函数
bool CServerSocketItem::OnSendCompleted(COverLappedSend * pOverLappedSend, DWORD dwThancferred);

//接收完成函数
bool CServerSocketItem::OnRecvCompleted(COverLappedRecv * pOverLappedRecv, DWORD dwThancferred);

为毛要区分Send OverLapped 和 Recv OverLapped呢,,,
应为投递一次Send不一定是瞬间完成的,在处理的过程中存储数据的内存应该是锁定的,也就是不允许修改的,,,所以OverLapped应该自己管理内存。
而recv应该也是需要有一片内存直接接受数据的,很奇怪netFox没有提供,,,

recv居然是在投递接受请求的时候给了一个空的buffer,然后在完成回调中自己再次调用recv方法接受数据。
接受有关的成员变量如下:
     // 状态变量
protected:
     bool                            m_bNotify;                             // 通知标志
     bool                            m_bRecvIng;                             // 接收标志
     bool                            m_bCloseIng;                         // 关闭标志
     bool                            m_bAllowBatch;                         // 接受群发
    WORD                            m_wRecvSize;                         // 接收长度
    BYTE                            m_cbRecvBuf[SOCKET_BUFFER*5];         // 接收缓冲

int iRetCode=recv(m_hSocket,(char *)m_cbRecvBuf+m_wRecvSize,sizeof(m_cbRecvBuf)-m_wRecvSize,0);
难道这么蠢的做法只是为了躲开分包算法?

回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | enginedx注册

本版积分规则

 
 



邮件留言:


 
返回顶部