/kanon

A event-driven network library based on Reactor(Inspired by muduo)

Primary LanguageC++MIT LicenseMIT

kanon

license code-top
win-build linux-build
version commit-date

Introduction

kanon是一个使用C++11编写的基于 事件驱动 (event-driven)的网络库(network libaray)。
具体来说,该库基于Reactor模式,其网络模型是同步非阻塞(synchronized-unblocking),依赖的的API是:poll()(unix-like/linux),epoll(linux)、GetQueuedCompletionStatusEx()(Windows)。
但是,实际上该库是暴露 回调注册接口 来处理各种IO事件,因此在使用上是类似异步的,这也是事件驱动的一个体现和优势。
除此之外,为了充分利用 多核优势 ,该库支持启动多个线程,而 主线程仅接受(accept)连接 ,而这些线程处理 IO事件 ,因此一般这些线程称作IO线程

注意:该库现在仅可在Windows和Linux编译,其中Windows目前仅支持Client,Server请不要使用!

另外,该库也实现了其他有用的组件,它们也是构成网络库的一部分,但对于编写应用程序的其他 非网络模块 也是十分有用的:

模块 描述 相关文件
log 支持输出到终端(terminal)/文件( 同步 或 异步 /kanon/log
thread Pthread:互斥锁(mutex),条件变量(condition),以及基于此实现的CountdownLatch /kanon/thread
string string_view的11等价实现,字符流和格式化流等 /kanon/string
util std::optionalmake_unique()的11等价实现,noncopyable /kanon/util
algo 支持O(1) append的单链表,支持reallocate的预分配数组等 /kanon/algo
... ... ...

更多的可以通过源码了解。

Buffer

对于网络库而言,想必对其使用的 读写缓冲区 (read/write buffer)很感兴趣,因为涉及 收发信息 (receive/send message)的性能。

缓冲 描述 相关文件
kanon::Buffer 缓冲,支持 prepend size header连续 容器,由于是基于kanon::ReservedArray实现的,因此比基于std::vector的性能要好 algo/reserved_array.h, buffer/buffer.h,cc
kanon::ChunkList 缓冲, 固定页面 的单链表(支持O(1) append),分配的节点除非用户主动收缩,否则不释放,自然也支持 prepend size header (因为每个节点本身就支持可变长度),细节参考相关文件 algo/forward_list.h, algo/forward_list/*, buffer/chunk_list.h,cc

之所以这么设计,是因为接受的信息一般需要 解析 / 反序列化 (parse/deserialize),因此如果不是连续的,那么得付出拼接完整信息的额外开销(overhead),这是划不来的,所以采用特化的连续容器。
而对于发送消息,我们并不关心其完整性,因此采用 基于节点 的非连续容器,即单链表可以避免因连续容器再分配带来的 memcpy 的开销。
实际上,通过ReservedArray实现的Buffer在一些情况下是可以进行 原地再分配 的(inplace reallocate),因此 benchmark 的结果表现略优于ChunkList,但根据现实的 工作负载 (workload)来考虑,写缓冲还是考虑用ChunkList,在我看来,这至少不是个坏主意(Bad IDEA)。
写缓冲支持size header的O(1) prepend,在我看来是个很不错的想法,在处理二进制协议时,这是十分有必要的,因此BufferChunkList都支持这个特性。

Build

kanon是通过cmake构筑的。因此你应该先安装cmake
如果你使用的是Ubuntu OS,那么可以通过以下命令安装:

$ sudo apt install cmake

然后通过以下命令构筑该库:

$ git clone https://github.com/conzxy/kanon
$ cd kanon
$ mkdir build && cd build
# Setting KANON_BUILD_STATIC_LIBS can choose to generate shared libaray(.so) or static libaray(.a)(default:ON)
# More options please see:
# cmake .. -LH
$ cmake ..
$ cmake --build . --parallel $(nproc)

构筑完成后,你可以安装该库:

# In */kanon/build
$ cmake --install .

如果你要修改安装路径,可以按照如下命令:

# 路径可以是绝对路径也可以是相对路径
# 如果是相对路径,CMake会认为这是相对prefix的路径
# prefix指定命令:
# cmake --install . --prefix ...
$ cmake .. -DCMAKE_INSTALL_INCLUDEDIR=... -DCMAKE_INSTALL_LIBDIR=...

Usage

安装了之后可以按照CMake的惯例做法使用kanon

CMake

[...]
find_package(kanon REQUIRED)
message(STATUS "Kanon version: ${KANON_VERSION}")

add_executable(kanon_test main.cc ...)
target_link_libraries(kanon_test PRIVATE kanon::kanon_base kanon::kanon_net)
[...]

Example

一个简单的例子是daytime服务器。
根据daytime协议,我们仅需要注册OnConnection回调即可。

void OnConnection(TcpConnectionPtr const& conn)
{
  conn->SetWriteCompleteCallback([](TcpConnectionPtr const& conn) {
    conn->ShutdownWrite();
  });

  conn->Send(GetDaytime());
}

除此之外,你也可以注册OnMessage回调以处理信息(比如请求等),还有其他回调你也可以参考tcp_connection.h

其他的例子可以参考example 目录。