最近朋友推荐,学习了libiop
这个网络库,作者封装的很全面,代码很简洁
适合初学者学习基于事件驱动
的网络io,先看看iop_def.h, 这里面定义了常用的数据结构
tag_iop_base_t
主要用于管理所有事件,每个事件是一个iop_t,
maxio
表示最大的文件描述符,
free_list_head
表示可用的空闲列表头部id,一般用iops + free_list_head
取出iop_t 的元素
同理free_list_tail
,最后一个可用iop,
iop_op_t
是封装了几个函数指针的结构体,
包括网络模型的名字,事件的添加
,事件的删除
,事件的更改
,事件的派发
剩下的如注释所示
1 | struct tag_iop_base_t |
看一下iop_t结构体
,id是从0开始到n的数,这个是在tag_iop_base_t
中初始化队列时做的,io_handle_t
是这个结构存储的socket id
, iop_type
分三种0表示释放
,1表示io读写
,2表示定时器事件
, iop_event_cb
表示事件回调函数指针
,每一个iop_t绑定了不同的回调函数,
比如accept,比如read,比如write,但是这些回调函数要封装成iop_event_cb类型
,dbuf_t
是作者封装的一个管理发送和接受数据的结构
1 | /* |
iop_event_cb 定义
如下
/事件回调函数,返回-1代表要删除对象,返回0代表正常/typedef int (*iop_event_cb)(iop_base_t *,int,unsigned int,void *);
dbuf_t结构如下
1 | struct tag_dbuf |
至于dbuf_t如何开辟空间释放空间,读写偏移的都不做赘述,iop_base_t中iop_op_t
结构很重要,是事件调度的核心
结构如下
1 | struct tag_iop_op_t |
因为对应不同的平台,我们要应用不同的网络模型,比如epoll,select,iocp等等。
但是对于异步通信IO我们采取事件回调机制,也就是说提前绑定好读事件,写事件等,
在循环中调用base_dispatch函数指针,就可以实现对于不同模型的派发。
上面就是libiop模型的基本结构和框架
我们看下epoll模型的封装
tag_epoll_data 是封装的epoll基本结构,
这个结构存在iop_base_t的model_data里
1 | struct tag_epoll_data { |
两个函数,iop_t应用层的读写宏
EV_TYPE_READ
和EV_TYPE_WRITE
epoll的读写宏EPOLLIN
和EPOLLOUT
互相转换
1 | static uint32_t to_epoll_events(uint32_t what) |
初始化epoll结构和数据
1 | int iop_init_epoll(void *iop_base, int maxev) |
对应的释放epoll开辟的空间和数据
1 | //epoll 释放 |
epoll 添加事件
1 | //epoll添加事件 |
epoll删除事件
1 | //epoll删除事件 |
epoll事件更改
1 | //epoll 模式更改(读写更改) |
epoll事件派发
1 | //epoll 事件派发 |
以上就是libiop事件驱动的核心结构和设计,做个简单的总结,如果我们要设计一个多路复用的事件驱动
基本结构是这样的
//eventEle是应用层管理的最小单元
int (*WRAFuc )(eventLoop* eventLoopP, int id, int mask, ...);
//mask为应用层自己定义的读写标记
1 | struct eventEle |
//事件轮询的基本结构
1 | struct eventLoop |
不同模型的操作进行封装成一个结构体,
结构体里面有添加,删除,更改,派发,释放的函数指针
1 | struct tag_iop_op_t |
这就是设计一个基本的事件驱动网络库的基本思路,
源代码下载地址:http://download.csdn.net/detail/secondtonone1/9517689