我要啦免费统计



库地址:


 


=========================


ST**表示单线程 




//开始监听

bool Startint nMaxMonitor );

//增加一个监听对象

bool AddMonitorSOCKET socket );

//等待事件发生,block无作用

bool WaitEventvoid *eventArrayint &countbool block );

//增加一个接受连接的操作,有连接进来,WaitEvent会返回

bool AddAccept(SOCKET listenSocket);

//增加一个接收数据的操作,有数据到达,WaitEvent会返回

bool AddRecvSOCKET socketcharrecvBufunsigned short bufSize );

//增加一个发送数据的操作,发送完成,WaitEvent会返回

bool AddSendSOCKET socketchardataBufunsigned short dataSize );











抽象控制的api

监听套接字对象的方法,

IOCPMonitor

==========================

typedef struct IO_EVENT

{

SOCKET sock;

EventType type;

SOCKET client;

char *pData;

unsigned short uDataSize;

}IO_EVENT;

MemoryPool m_iocpDataPool;//iocp投递参数池

typedef struct IOCP_OVERLAPPED

{

/**

 * OVERLAPPED类型指针

 * 指向完成操作参数

 * 传递给AcceptEx()的最后一个参数

 * 传递给WSARecv()的第个参数

 * GetQueuedCompletionStatus()返回的第个参数

 */

OVERLAPPED m_overlapped;

/**

 * 指向存有连接进来的客户端局域网和外网地址的内存

 * 必须使用动态分配的内存块

 * 传递给AcceptEx()的第个参数

 * 

 */

char m_outPutBuf[sizeof(SOCKADDR_IN)*2+32];

/**

 * 客户端局域网IP信息长度

 * 传递给AcceptEx()的第个参数

 */

unsigned long m_dwLocalAddressLength;

/**

 * 客户端外网IP信息长度

 * 传递给AcceptEx()的第个参数

 */

unsigned long m_dwRemoteAddressLength;

WSABUF m_wsaBuffer;//WSARecv接收缓冲数据,传递给WSARecv()的第个参数

SOCKET sock;

EventType completiontype;//完成类型recv 2send

}IOCP_OVERLAPPED;

IOCPMonitor::Start( int nMaxMonitor ) 

端口启动 

创建完全端口 

线程数cpu数*2+2

IOCPMonitor::AddMonitor( SOCKET sock )

加入套接字到 IOCP列队

IOCPMonitor::WaitEvent( void *eventArray, int &count, bool block )

等待一次完全端口的 事件

GetQueuedCompletionStatus( )

返回不同的iocp事件类型 或 数据 供上层循环控制

IOCPFrame : public NetEngine  

继承了 netengine 的通用和抽象的方法,

同时针对不同的os平台实例化不同的网络模型 

IOCPFrame::IOCPFrame()

{

#ifdef WIN32

m_pNetMonitor = new IOCPMonitor;

#endif

IOCPFrame  控制监听 接收 发送,集成 NetEngine   抽象

Child: one new IOCPMonitor;

class NetServer

{

friend class NetEngine;

NetEnginem_pNetCard;

Netserver为 主要控制对象,里面抽象了逻辑的控制的 函数,可以继承城市

同时 NetServer 和 NetEngine 是friend class 

NetEngine 里面有监听过程中的 一些写业务的逻辑调用到 Netserver,几个抽象的业务 接口 实现的地方 就独立出来了。

NetEngine 业务控制抽象的几种 业务调用

Threeadpool的任务




三种:业务实现

OnConnect

Onclose 

OnMsg

比如



监听到链接的 调用NetEngine 调用了 iocpframe监听 到连接的事件

调用父辈方法

NetEngine::OnConnectSOCKET sockbool isConnectServer )

创建一个 NetConnect对象,通过内存池分配的对象

投递一个 连接的任务的task给线程池

Onclose 

OnMsg

类似

内存池设计

内存池 存储 NetConnect对象,存储管理netconnect对象 使用memorypool

//初始化内存池 预分配内存池

bool Init(unsigned short uMemorySizeunsigned short uMemoryCount);

// //分配内存(链表方法) 

一个线程读 一个线程写 无锁队列

Iobuffer  

包含vector 一张 Iobufferblock 表,存储多个缓冲块

读取的时候

Iobufferblock 托管在内存池mempool BUFBLOCK_SIZE大小的内存块

Iobuffer

Readdata

/**

 * IO缓冲

 * 定义宏BUFBLOCK_SIZE

 * 编译期静态确定类大小

 * 不能使用指针在运行时动态指定大小,参考池对象使用限制二

 */

unsigned char m_buffer[BUFBLOCK_SIZE];

//已收到数据的长度

unsigned short m_uLength;

//Recv()函数下次读取数据的开始位置

unsigned short m_uRecvPos;

unsigned short IOBufferBlock::ReadDataunsigned char *dataunsigned short uLengthbool bDel )

从当前读取位置开始读取,如果越界 就用剩下的大小获取

bool IOBuffer::ReadDataunsigned char *dataint uLengthbool bDel )

//这里检查m_uDataSize不需要原子操作

//cpu与内存次交换最小长度就是byte,对于小于等于byte的类型的取值/赋值操作,

//本身就是原子操作

从头来 

遍历 所有bufferblock 如果是需要删除的,那么原子操作减一,标志不使用了内存池,同时删除清理block

一读一写,没有线程安全问题

====================

SharedPtr

通过原子加减操作达到 引用计数操作的线程安全

ShareMemory

依靠viewmap实现 内存映射文件

/*

 * 创建/打开共享内存

 * 参数

 * key 全局标识,linux下只接收数字id

 * size 共享大小

 * if ( 是创建)

 * 则创建size大小的共享内存,

 * else //是打开已存在的共享内存

 * if ( 是文件映射&& 是linux系统)

 *   则使用当前共享内存大小与size中较大的一个,作为共享内存的大小

 * else 无效

 * else 无效

 * path 使用文件映射的共享内存,文件路径,key为文件名

 */

ShareMemory(const char *keyunsigned long sizeconst char *path);

/*

 * 创建/打开共享内存

 * 参数

 * key 全局标识

 * size 共享大小

 * if ( 是创建)

 * 则创建size大小的共享内存,

 * else //是打开已存在的共享内存

 * if ( 是文件映射&& 是linux系统)

 *   则使用当前共享内存大小与size中较大的一个,作为共享内存的大小

 * else 无效

 * else 无效

 * path 使用文件映射的共享内存,文件路径,key为文件名

*/

ShareMemory(const int keyunsigned long sizeconst char *path);

public:

voidGetBuffer();

unsigned long GetSize();

void Destory();

一次性获取数据,初始化的时候指定 了大小了。

内存映射文件的方法,没啥好看的

Signal

采用事件做信号通知,

=========================================

ThreadPool 

包含一个vect的任务队列 里面带的就是task

线程池 采用 事件信号通知。执行的函数 ThreadFunc

每次从 从m_tasks取任务,加了锁地取法。

然后执行task的里面的Execute 方法 这样就调用到 ExecutorCallMethod方法 参数从入队进入就提交了。

Memorypool






















一、

一块对象数据MEMERY_INFO + uMemorySize













二、一个 MemoryPool 数据结构

存储对象本身 8Byte

每一块数据包含信息8byte 然后就是指向 目标管理对象的对象内存

nBlockStartPos += MEMERY_INFO;

pObject = &(m_pMemery[nBlockStartPos]);

内存块数 初始化的时候 设置的 m_uMemoryCount






三、Alloc()

找寻本身memorypool是否存在可用内存,

有,就直接获取地址出去使用

没有的的话遍历到最后会发现 pBlock->m_pNext 为空,这个时候重新new memorypool对象 教导链表上去


m_uFreeCount 未分配的 个数

通过遍历 查询AtomDec  pBlock->m_uFreeCount 减1 

if ( 0 < (int32)AtomDec(&pBlock->m_uFreeCount, 1) ) break; 执行分配

class MemoryPool   voidAlloc();

 * 无锁堆(n读n写并发,不需加锁)

 *  内存池结构

 *  n个池组成链表

 * 

 *  池结构

 *  每个池都是一段连续内存保存在char数组中

 *  0~7byte为池地址,后面是n个用于固定长度分配的内存块(即内存块是定长的)

 * 

 *  内存块结构

 *  状态byte+留空byte+内存块块序号byte

 *  所以一个内存池最大可以保存的对象(内存块)数量为unsigned short的最大值

 *

 * 状态就个(分配/未分配),个byte就可以表示,使用byte是为了使用原子操作实现lock-free,而原子操作操作的是byte地址

 * 2byte留空,是为了保证后面用于分配的内存守地址都是byte对齐

 *  因为真实new出来的对象首地址是保证这点的,

 *  且IOCP投递缓冲struct,也要求首地址对齐,否则返回错误

初始化

//预分配内存=MemoryPool对象自身地址,byte,支持位机寻址

//记录对象地址 

//头个字节保存对象自身地址,用于从内存地址找到内存池对象地址

if ( 8 == uAddrSize )

{

m_pMemery[nPos++] = (unsigned char)(uThis >> 56);

m_pMemery[nPos++] = (unsigned char)(uThis >> 48);

m_pMemery[nPos++] = (unsigned char)(uThis >> 40);

m_pMemery[nPos++] = (unsigned char)(uThis >> 32);

}

else

{

m_pMemery[nPos++] = 0;

m_pMemery[nPos++] = 0;

m_pMemery[nPos++] = 0;

m_pMemery[nPos++] = 0;

}

m_pMemery[nPos++] = (unsigned char)(uThis >> 24);

m_pMemery[nPos++] = (unsigned char)(uThis >> 16);

m_pMemery[nPos++] = (unsigned char)(uThis >> 8);

m_pMemery[nPos++] = (unsigned char)uThis;

//初始化内存

unsigned short i;

for ( i = 0; i < m_uMemoryCounti++ )

{

//状态未分配

m_pMemery[nPos++] = 0;

m_pMemery[nPos++] = 0;

m_pMemery[nPos++] = 0;

m_pMemery[nPos++] = 0;

//留空字节

m_pMemery[nPos++] = 0;

m_pMemery[nPos++] = 0;

//保存内存序号

m_pMemery[nPos++] = (unsigned char) (i >> 8);

m_pMemery[nPos++] = (unsigned chari;

nPos += uMemorySize;

}

链表 内存池组

每个内存池 

通过对象算出索引

通过索引算出对象都很方便

详细参考另外一个笔记


posted on 2013-06-25 20:02 阅读(2720) 评论(3)  编辑 收藏 引用 所属分类: 测试训练

评论:
# re: Micro-Development-Kit 学习记录 mdk 高性能网络库 2013-06-28 04:10 | buyessay
以 博主客通 返回页首 恢复上次提交 过“恢名  回复  更多评论
  
# re: Micro-Development-Kit 学习记录 mdk 高性能网络库 2014-09-15 18:52 | Amber
http://special-essays.com is one of those essay writing companies, which do their very best to make the customers 100% satisfied with their services.   回复  更多评论
  
# re: Micro-Development-Kit 学习记录 mdk 高性能网络库 2014-12-17 16:16 | Ashley
hey hey!i am here accidentally and want to share with you the best site ever where you can order a unique essay for low price. http://best-essays-writers.org is a highly reputable online writing company where you can buy essays of all types at a cheap price.  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理