对libuv的C++封装

7次阅读

共计 1175 个字符,预计需要花费 3 分钟才能阅读完成。

libuv_cpp11 是一个基于 libuv 的 C ++ 封装网络库。接口较为简单易用,并对 libuv 一些特性做了扩展及优化。压力测试结果稳定、高效。未发现内存泄漏及崩溃。
为什么需要封装 libuv
截至目前,C++ 没有标准网络库,常见的有 ACE 和 boost.asio。ACE 较为庞大臃肿,封装复杂,个人不推荐。boost.asio 是 boost 库的一部分,需要依赖 boost 的部分实现,使用 asio 需要在项目引入较为庞大的 boost 库。而 C 语言的网络库主要有 libevent、libev 及 libuv。libuv 是 nodejs 的底层,较为成熟。所以如果在项目需要一套轻量级,且没有太多依赖的网络组件,最好的办法,还是自己封装一套。
libuv_cpp11 功能简介
1. 实现了 C ++ 功能的回调首先 libuv 是一个 C 语言库,意味着回调函数是 C 语言的回调,所以直接使用 libuv 网络消息回调,相关对象必须是全局的或者 static 对象,这是令人难以容忍的。这里通过 libuv 的用户数据功能实现了 C ++ 风格的回调,回调函数可以类成员函数,或者 lambda。同时封装了 TcpServer 及 TcpClient 等类,简化编程。
2. 对线程安全做了优化 libuv 是一个非线程安全的库,跨线程发送数据数不允许的。libuv_cpp11 中实现了线程安全的跨线程 write 数据操作。基于 libuv 的 async 异步机制实现,同时在跨线程调用时候会检查当前调用线程,如果在该 loop 线程中则直接发送,减少了不必要的性能损耗。实现如下:
void uv::EventLoop::runInThisLoop(const std::function<void()>& func)
{
if (nullptr == func)
return;

if (isRunInLoopThread())
{
func();
return;
}
async_->runInThisLoop(func);
}
同时 libuv 的 aysnc 接口存在多次调用一次执行的可能(问题),比如有些操作需要在回调里面释放数据,这样就会内存泄漏。libuv_cpp11 中的 Async 类优化这个问题,确保每次调用一定会被执行。
3. 实现了定时器及时间轮对 libuv 定时器做了一层封装,并实现了一个时间复杂度 O(1) 的时间轮,用于检测心跳超时。
4. 实现整包发送 / 接受协议机制实现了 ListBuffer 和 CycleBuffe 两种缓存机制,用于解决 TCP 的粘包及残包。数据会重新组成完整的包数据用于读取。性能测试显示 CycleBuffe 会损失 20%~30% 的性能。
5 日志接口 libuv_cpp11 没有实现日志功能,但是保留了接口,可以注册 / 绑定到自定义日志库中使用。
libuv_cpp11 的使用
详见 example 文件夹:https://github.com/wlgq2/libu…

正文完
 0