非阻塞网络编程实例讲解
一、概述
acl 库的 C 库(lib_acl) 的 aio 模块设计了完整的非阻塞异步 IO 通信过程,在 acl 的C++库(lib_acl_cpp) 中封装并增强了异步通信的功能,本文主要描述了 acl C++ 库之非阻塞IO库的设计及使用方法,该异步流的设计思路为:异步流类与异步流接口类,其中异步流类对象完成网络套接口监听、连接、读写的操作,异步流接口类对象定义了网络读写成功/超时回调、连接成功回调、接收客户端连接回调等接口;用户在进行异步编程时,首先必须实现接口类中定义的纯方法,然后将接口类对象在异步流对象中进行注册,这样当满足接口类对象的回调条件时 acl_cpp 的异步框架便自动调用用户定义的接口方法。
在 acl_cpp 中异步流的类继续关系如下图所示:
由上图可以看出,基类 aio_stream 中定义了流关闭,注册/取消流关闭回调和流超时回调等基础方法;aio_istream 和 aio_ostream 分别定义了异步流读及写的基本方法,aio_istream 中包含添加/删除流读成功回调接口类对象的方法,aio_ostream 中包含添加/删除流写成功回调接口类对象的方法;aio_socket_stream 类对象为连接服务器成功后的客户端流,或服务器接收到客户端连接创建的客户端连接流,其中定义了做为连接流时远程连接的方法及添加连接成功回调接口的方法;aio_listen_stream 类为监听流类,其中定义了监听某个网络地址(或UNIX下的域套接口地址)方法,以及注册接收成功接口的方法。
acl_cpp 异步流接口类继承关系图如下图:
异步流接口类的设计中:aio_accept_callback 为监听流的回调接口类,用户应继承该类以获得外来客户端连接流,同时还需要定义继承于 aio_callback 的类,用于获得网络读写操作等结果信息;aio_open_callback 只有当客户端连接远程服务器时,用户需要实现其子类获得连接成功的结果。
二、实例
1、异步服务器
1 |
|
简要说明一下,上面代码的基本思路是:
- 创建异步通信框架对象 aio_handle –> 创建异步监听流 aio_listen_stream 并注册回调类对象 io_accept_callback–>进入异步通信框架的事件循环中;
- 当接收到客户端连接后,异步框架回调 io_accept_callback 类对象的 accept_callback 接口并将客户端异步流输入–>创建异步流接口类对象,并将该对象注册至客户端异步流对象中;
- 当客户端异步流收到数据时回调异步流接口中的 read_callback 方法 –> 回写收到数据至客户端;当客户端流连接关闭时回调异步流接口中的close_callback –> 如果该接口类对象是动态创建的则需要手工 delete 掉;当接收客户端数据超时时会回调异步流接口中的 time_callback,该函数如果返回 true 则表示希望异步框架不关闭该客户端异步流,否则则关闭。
异步监听流的接口类的纯虚函数:virtual bool accept_callback(aio_socket_stream* client) 需要子类实现,子类在该函数中获得客户端连接异步流对象。
客户端异步流接口类 aio_callback 有四个虚函数:
virtual bool read_callback(char* data, int len)
当客户端异步流读到数据时的回调虚函数;virtual bool write_callback()
当客户端异步流写数据成功后的回调虚函数;virtual void close_callback()
当异步流(客户端流或监听流)关闭时的回调虚函数;virtual bool timeout_callback()
当异步流(客户端流在读写超时或监听流在监听超时)超时时的回调函数虚函数。
2、异步客户端
1 |
|
异步客户端的基本流程为:
- 创建异步框架对象 aio_handle –> 异步连接远程服务器,创建连接成功/失败/超时的异步接口类对象并注册至异步连接流中 –> 异步框架进行事件循环中;
- 连接成功后,异步接口类对象中的 open_callback 被调用,启动下一个异步连接过程(未达限制连接数前) –> 添加异步读及异步写的回调接口类 –> 异步写入数据,同时开始异步读数据过程;
- 当客户端异步流收到数据时回调异步流接口中的 read_callback 方法 –> 回写收到数据至客户端;当客户端流连接关闭时回调异步流接口中的 close_callback –> 如果该接口类对象是动态创建的则需要手工 delete 掉;当接收客户端数据超时时会回调异步流接口中的 time_callback,该函数如果返回 true 则表示希望异步框架不关闭该客户端异步流,否则则关闭。
客户端异步连接流的接口类 aio_open_callback 的纯虚函数 virtual bool open_callback() 需要子类实现,在连接服务器成功后调用此函数,允许子类在该函数中做进一步操作,如:注册客户端流的异步读回调接口类对象及异步写回调类对象;如果连接超时或连接失败而导致的关闭,则基础接口类中的 timeout_callback() 或 close_callback() 将会被调用,以通知用户应用程序。
三、小结
以上的示例演示了基本的非阻塞异步流的监听、读写、连接等过程,类的设计中也提供了基本的操作方法,为了应对实践中的多样性及复杂性,acl_cpp 的异步流还设计了更多的接口和方法,如:延迟读写操作(这对于限流的服务器比较有用处)、定时器操作等。
更多例子参见:lib_acl_cpp/samples/aio/ 目录
github:https://github.com/acl-dev/acl
gitee:https://gitee.com/acl-dev/acl