
## 简介
CppNet是一个封装在Tcp协议上的Proactor模式multi-thread C++11网络库,目前支持在windows和linux上编译使用。
简单:对外只导出了少量的调用接口,所有的网络IO都封装为异步回调的形式,且接口声明都尽可能的像是调用系统socket API,对客户端而言,只多了一个新增的buffer对象类型。
快速:分别采用epoll和IOCP做底层事件驱动,其中epoll多线程惊群通过端口复用交由Linux内核处理。参照SGI STL和Nginx实现了内存池,每个建立连接的socket都独享一个内存池对象,所有从内存池中申请的内存都由智能指针管理。
明了:结构上分为三层:事件驱动层,会话管理层,接口层,各层之间通过回调向上通知。各个模块之间职责分工明确,上帝的事儿归上帝管,凯撒的事儿归凯撒管。最大的类不超过500行代码。
## 接口
所有的接口文件都在 [include](/include) 中,其中关于库初始化和定时器的接口定义在 [CppNet](/include/CppNet.h) 中:
```c++
// common
// init cppnet library.
// thread_num: the number of running threads.
void Init(int32_t thread_num);
void Dealloc();
// thread join
void Join();
// must set callback before listen
void SetReadCallback(const read_call_back& func);
void SetWriteCallback(const write_call_back& func);
void SetDisconnectionCallback(const connection_call_back& func);
//timer
uint64_t SetTimer(int32_t interval, const timer_call_back& func, void* param = nullptr, bool always = false);
void RemoveTimer(uint64_t timer_id);
//server
void SetAcceptCallback(const connection_call_back& func);
bool ListenAndAccept(int16_t port, std::string ip);
//client
void SetConnectionCallback(const connection_call_back& func);
```
因为所有的网络IO接口都被定义为回调通知的模式,所以初始化库的时候需要设置各个调用的回调函数。
这里通过设置回调而不是提供虚函数继承的方式,是希望尽量的简单,减少类的继承关系,增加回调的灵活性,你可以将回调设置为任意一个函数。
关于网络IO的接口定义在[Socket](/include/Socket.h)中:
```c++
// get socket ip and adress
int16_t GetIpAddress(const Handle& handle, std::string& ip, uint16_t& port);
// post sync write event.
int16_t Write(const Handle& handle, const char* src, int32_t len);
// post a sync task to io thread
int16_t PostTask(std::function& func);
#ifndef __linux__
// sync connection.
int16_t Connection(const std::string& ip, int16_t port, const char* buf, int32_t buf_len);
#endif
int16_t Connection(const std::string& ip, int16_t port);
int16_t Close(const Handle& handle);
```
接口的作用通过声明和注释即可明了。需要关注的是接口返回的错误码,与回调函数的声明一起定义在[CppDefine](/include/CppDefine.h)中:
```c++
enum CPPNET_ERROR_CODE {
CEC_SUCCESS = 1, // success.
CEC_TIMEOUT = 2, // the event time out call back.
CEC_CLOSED = 3, // remote close the socket.
CEC_INVALID_HANDLE = 4, // invalid cppnet handle, can't find in socket manager.
CEC_FAILED = 5, // call function failed.
CEC_CONNECT_BREAK = 6, // connect break.
CEC_CONNECT_REFUSE = 7 // remote refuse connect or server not exist.
};
```
每个接口在采取下一步动作时应先检测一下当前返回的错误码,以获知当前连接是否正常。
## 示例
所有示例都在 [test](/test) 目录下:
[simple](/test/simple)是一个简单的使用示例。
[echo](/test/echo)实现了10000连接量的echo的测试程序。
[http](/test/http)参照muduo实现了一个简单的http服务器。
[sendfile](/test/sendfile)是一个文件发送和接收示例。
[pingpong](/test/pingpong)是一个pingpong测试程序。
[rpc](/test/rpc)是一个简单的rpc示例。
## 效率
目前只用ab做了http echo测试,与muduo做了对比,执行的命令为:ab -kc[1-2000] -n100000 http://127.0.0.1:8000/hello.

## 编译(Windows)
你可以使用vs2017来编译CppNet库和示例。
## 编译(Linux)
只需要在源码目录下执行make即可编译CppNet库和示例。
其他示例则需要在编译完静态库之后,分别在本地目录里执行make。
```
$ make -j4
```
## 协议
CppNet使用BSD 3-Clause使用条款,详情请看[https://opensource.org/licenses/BSD-3-Clause](https://opensource.org/licenses/BSD-3-Clause)。