Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

f9865/tinyev

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

81 Commits

Repository files navigation

tinyev: A multithreaded C++ network library

Build Status

简介

tinyev是仿照muduo[1]实现的一个基于Reactor模式的多线程C++网络库,经过适当简化以后代码量约为2000行。简化的部分如下:

  • 多线程依赖于C++11提供的std::thread库,而不是重新封装POSIX thread API。

  • 定时器依赖于C++11提供的std::chrono库,而不是自己实现Timstamp类,也不用直接调用gettimeofday()。这样写的好处之一是我们不必再为定时器API的时间单位操心[2]:

    using namespace std::literals::chrono_literals;
    loop.runEvery(10s, [](){INFO("run every 10 seconds");});
    loop.runAfter(24h, [](){INFO("run after 24 hours");});
    loop.runAt(Clock::nowAfter(15min), [](){INFO("run 15 minutes later");});
  • 默认为accept socket开启SO_RESUEPORT选项,这样每个线程都有自己的Acceptor,就不必在线程间传递connection socket。开启该选项后内核会将TCP连接分摊给各个线程,因此不必担心负载均衡的问题。

  • 仅具有简单的日志输出功能,用于调试。

  • 仅使用epoll,不使用poll和select。

示例

一个简单的echo服务器如下:

class EchoServer: noncopyable
{
public:
 EchoServer(EventLoop* loop, const InetAddress& addr)
 : loop_(loop),
 server_(loop, addr),
 {
 // set echo callback
 server_.setMessageCallback(std::bind(&EchoServer::onMessage, this, _1, _2));
 }
 void start() { server_.start(); }
 void onMessage(const TcpConnectionPtr& conn, Buffer& buffer)
 {
 // echo message
 conn->send(buffer);
 }
private:
 EventLoop* loop_;
 TcpServer server_;
};

这个实现非常简单,读者只需关注onMessage回调函数,它将收到消息发回客户端。然而,该实现有一个问题:若客户端只发送而不接收数据(即只调用write而不调用read),则TCP的流量控制(flow control)会导致数据堆积在服务端,最终会耗尽服务端内存。为解决该问题我们引入高/低水位回调:

class EchoServer: noncopyable
{
public:
 ...
 void onConnection(const TcpConnectionPtr& conn)
 {
 if (conn->connected())
 conn->setHighWaterMarkCallback(
 std::bind(&EchoServer::onHighWaterMark, this, _1, _2), 1024);
 }
 void onHighWaterMark(const TcpConnectionPtr& conn, size_t mark)
 {
 INFO("high water mark %lu bytes, stop read", mark);
 conn->stopRead();
 }
 void onWriteComplete(const TcpConnectionPtr& conn)
 {
 if (!conn->isReading()) {
 INFO("write complete, start read");
 conn->startRead();
 }
 }
 ...
};

我们新增了3个回调:onConnection,onHighWaterMarkonWriteComplete。当TCP连接建立时onConnection会设置高水位回调值(high water mark);当send buffer达到该值时,onHighWaterMark会停止读socket;当send buffer全部写入内核时,onWriteComplete会重新开始读socket。

除此以外,我们还需要给服务器加上定时功能以清除空闲连接。实现思路是让服务器保存一个TCP连接的std::map,每隔几秒扫描一遍所有连接并清除超时的连接,代码在这里

然后,我们给服务器加上多线程功能。实现起来非常简单,只需加一行代码即可:

EchoServer::void start()
{
 // set thread num here
 server_.setNumThread(2);
 server_.start();
}

最后,main函数如下:

int main()
{
 EventLoop loop;
 // listen address localhost:9877
 InetAddress addr(9877);
 // echo server with 4 threads and timeout of 10 seconds
 EchoServer server(&loop, addr, 4, 10s);
 // loop all other threads except this one
 server.start();
 // quit after 1 minute
 loop.runAfter(1min, [&](){ loop.quit(); });
 // loop main thread
 loop.loop();
}

安装

$ git clone git@github.com:guangqianpeng/tinyev.git
$ cd tinyev
$ git submodule update --init --recursive
$ ./build.sh 
$ ./build.sh install

tinyev安装在 ../tinyev-build/Release/{include, lib}

更多

网络库的具体实现方法参考我的博客

参考

[1] Muduo is a multithreaded C++ network library based on the reactor pattern.

[2] CppCon 2017: Bjarne Stroustrup "Learning and Teaching Modern C++". Make interfaces precisely and strongly typed.

About

Multithreaded network library in C++17

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 93.5%
  • C 3.7%
  • CMake 2.5%
  • Shell 0.3%

AltStyle によって変換されたページ (->オリジナル) /