Tiny C++ Network Library
| Part Ⅰ | Part Ⅱ | Part Ⅲ | Part Ⅳ | Part V | Part Ⅵ | Part Ⅶ |
|---|
| Project Introduction | Project Features | Development Environment | Concurrency Model | Build a project | Running cases | Module explanation |
Project Introduction
This project is a multi-threaded network library based on the Reactor model implemented by muduo. Using C++11 to write to remove muduo's dependence on boost, a small HTTP server is implemented internally, which can support GET requests and access to static resources, and is accompanied by asynchronous logs to monitor the server situation.
The project has implemented Channel module, Poller module, event loop module, HTTP module, timer module, asynchronous log module, memory pool module, and database connection pool module.
Project Features
- The underlying layer uses the I/O multiplexing model of Epoll + LT mode and implements the master-slave Reactor model in combination with non-blocking I/O.
- Adopt the "one loop per thread" thread model and encapsulate the thread pool upward to avoid the performance overhead caused by thread creation and destruction.
- Eventfd is used as the event notification descriptor to facilitate efficient dispatch of events to other threads to perform asynchronous tasks.
- Asynchronous logs are implemented based on self-implemented double buffers, and the backend thread is responsible for writing front-end log information to the disk regularly to avoid blocking network services when data falls off the disk.
- The timer management structure is implemented based on the red and black tree, and the timerfd of Linux is used internally to notify expiration tasks, and timed tasks are efficiently managed.
- Follow RAII techniques to manage memory using smart pointers to reduce the risk of memory leakage.
- Use finite state machines to parse HTTP request packets.
- Referring to Nginx, the memory pool module is implemented to better manage small memory space and reduce memory fragmentation.
- The database connection pool can dynamically manage the number of connections, generate or destroy connections in a timely manner, and ensure the performance of the connection pool.
Development Environment
- Operating System:
Ubuntu 18.04.6 LTS - Compiler:
g++ 7.5.0 - Editor:
vscode - Version control:
git - Project construction:
cmake 3.10.2
Concurrency Model
The project adopts the master-slave Reactor model. MainReactor is only responsible for listening and dispatching new connections. In MainReactor, new connections are received through Acceptor and polled to SubReactor. SubReactor is responsible for read and write events of this connection.
After calling the start function of TcpServer, a thread pool will be created internally. Each thread runs an event loop independently, namely SubReactor. MainReactor polls the SubReactor from the thread pool and dispatches it to a new connection. The number of SubReactors that handle read and write events is generally equal to the number of CPU cores. There are many advantages to using the master-slave Reactor model:
- Fast response and does not have to be blocked by a single synchronization event, although Reactor itself is still synchronous;
- It can avoid complex multi-threading and synchronization problems to the greatest extent, and avoid multi-threading/process switching;
- It has good scalability, which can facilitate the full use of CPU resources by increasing the number of Reactor instances;
- The reusability is good, and the Reactor model itself has nothing to do with the specific event processing logic and has high reusability;
Build a project
Install Cmake
sudo apt-get update
sudo apt-get install cmake
Download the project
Execute script build project
cd ./tiny-network && bash build.sh
Running cases
Here we take a simple echo server as a case, and the default listening port of EchoServer is 8080 .
cd ./example
./EchoServer
Implementation status:
The http module has a small HTTP server case that can also be executed. Its default listening 8080 :
cd ./src/http && ./HttpServer
Module explanation
Some modules here will configure muduo source code to explain, and some use the source code of this project, but the implementation ideas are consistent.
Channel module
Poller module
EventLoop module
Buffer module
Timer module
HTTP module
Asynchronous log module
Memory pool module
Database connection pool module
Optimization plan
- Plan to implement the underlying timestamp using std::chrono
- Manage timer structure using priority queue
- Coverage more unit tests
grateful
- "Linux High Performance Server Programming"
- "Linux multithreaded server programming: using muduo C++ network library"
- https://github.com/chenshuo/muduo