内容简介:github.com/idealvin/co co 是一个优雅、高效的 C++ 基础库,支持 Linux, Windows 与 Mac 平台,它包含协程库、网络库、日志库、命令行与配置文件解析库、单元测试框架、JSON 库等基本组件。 co 遵循极简的设计理...
co 是一个优雅、高效的 C++ 基础库,支持 Linux, Windows 与 Mac 平台,它包含协程库、网络库、日志库、命令行与配置文件解析库、单元测试框架、JSON 库等基本组件。
co 遵循极简的设计理念,提供的接口都尽可能简单明了,用户可以轻松上手。co 尽量避免过度封装,引入过多的概念,以减轻用户的学习负担,如 co 提供的协程化的 socket API,与原生 socket API 形式上基本一致,熟悉 socket 编程的用户,几乎不需要增加新的学习成本,就能轻松用这些 API 写出高性能的网络程序。
详细的参考文档
首先特别强调的是,这次提供了更加详细的参考文档:
这次直接将文档放到语雀上了,它的目录编排做得不错。有现成的平台,就直接拿来用了,懒得再去折腾个人网站啥的.. 大家可以去上面留言、提建议..
新特性
SSL
co 2.0 终于支持 SSL 了,用户需要安装 openssl 1.1 以上的版本,目前已在 openssl 上测试通过,其他 SSL 库暂未测试。
推荐使用 xmake 编译,它会提示用户是否安装 openssl, libcurl, zlib 等三方库。要启用 SSL 特性,需要预定义 CO_SSL
宏,xmake 在检测到 openssl 时会自动定义这个宏。
co/so/ssl.h 中提供了协程化的 openssl 接口,不过用户很可能不会直接使用它们,因为 co 已经将 SSL 功能内嵌到 TCP 模块中,用户可以直接使用 tcp::Server 与 tcp::Client。
重要改进
协程
- go()
go() 支持任意带 0 个或 1 个参数的函数或类方法,以及std::function<void()>
类型的函数对象或指针。
void f();
void g(int);
void h(int, int);
struct T {
void f();
void g(int);
};
T o;
std::function<void()> k(std::bind(h, 3, 7));
go(f);
go(g, 7);
go(&T::f, &o);
go(&T::g, &o, 3);
go(k);
go(&k); // The user must ensure that k is alive when the coroutine is running.
- 协程 API
- 增加 co::timeout() 函数,用户可以用它判断上次调用的 co::recv(), co::send() 等 I/O 函数是否超时。
- co::coroutine_id() 函数返回一个全局唯一的 id,1.x 版本中,不同调度线程中的协程可能有相同的 id。
- co::Event
内部增加 signaled 状态,解决没有协程等待的情况下,同步信号会丢失的问题。
- co::IoEvent
1.x 版本中仅在内部使用,2.0 中公开这个类,方便用户自行将三方网络库协程化。
int recv(SSL* s, void* buf, int n, int ms) {
CHECK(co::scheduler()) << "must be called in coroutine..";
int r, e;
int fd = SSL_get_fd(s);
if (fd <0) return -1;
do {
ERR_clear_error();
r = SSL_read(s, buf, n);
if (r> 0) return r; // success
if (r == 0) {
DLOG << "SSL_read return 0, error: "<< SSL_get_error(s, 0);
return 0;
}
e = SSL_get_error(s, r);
if (e == SSL_ERROR_WANT_READ) {
co::IoEvent ev(fd, co::EV_read);
if (!ev.wait(ms)) return -1;
} else if (e == SSL_ERROR_WANT_WRITE) {
co::IoEvent ev(fd, co::EV_write);
if (!ev.wait(ms)) return -1;
} else {
DLOG << "SSL_read return "<< r << ", error:" << e;
return r;
}
} while (true);
}
- 上面是将 openssl 中的 SSL_read() 函数协程化的例子,只需要使用 non-blocking socket,在 openssl 产生 SSL_ERROR_WANT_READ 或 SSL_ERROR_WANT_WRITE 错误时,调用 co::IoEvent 的 wait() 方法,等待相应的 I/O 事件即可。
TCP
- 新增 tcp::Connection 类,用于 TCP server 的实现,该类提供了 recv(), send() 等方法,用户可以直接用该类接收、发送数据,而无需关心底层是否启用了 SSL。
- tcp::Server
void on_connection(tcp::Connection* conn);
tcp::Server s;
s.on_connection(on_connection);
s.start("0.0.0.0", 7788); // no ssl
s.start("0.0.0.0", 7788, "privkey.pem", "certificate.pem"); // use ssl
tcp::Server 只需要在 start() 方法中指定 SSL private key 与证书文件,即可启用 SSL。
- tcp::Client
bool use_ssl = false;
tcp::Client c("127.0.0.1", 7788, use_ssl);
c.connect(1000);
c.send(...);
tcp::Client 可以通过构造函数的第 3 个参数启用 SSL。
HTTP
- http::Client
co 2.0 中,http::Client 基于 libcurl 实现,要启用此特性,必须安装 libcurl,并预定义HAS_LIBCURL
宏。还是那句话,建议用 xmake 构建,它会自动搞定这些三方依赖。
http::Client c("https://github.com");
http::Client c("http://127.0.0.1:7777");
c.get("/");
c.get("/idealvin/co");
LOG << c.response_code();
- http::Server
基于 tcp::Server 实现,只要在 start() 方法中带上 SSL 私钥及证书文件,就能启用 SSL。
http::Server s
s.on_req(...);
s.start("0.0.0.0", 7777); // http
s.start("0.0.0.0", 7777, "privkey.pem", "certificate.pem"); // https
RPC
co 2.0 中,RPC 框架添加了一些新特性:
- 支持 SSL。
- 支持用户名与密码认证,RPC server 可以设置多个用户名、密码。
- rpc::Server 可以添加多个 service。
- RPC 代码生成器可以生成 RPC client 代码。
JSON
1.x 版本中,JSON 库仅用一个 json::Value
类表示 JSON,JSON 对象中的元素也是 json::Value,构建 JSON 对象时需要为每个元素分配内存,JSON 对象析构时,内部所有元素都要调用 json::Value
的析构函数。基于这种方式的实现,会导致频繁的内存分配及释放操作,非常影响程序性能。
co 2.0 中,将 JSON 对象构建到一块连续的内存上,程序运行稳定后,解析 JSON 几乎不需要内存分配操作,大大提高了 parsing 速度,实测可以达到 rapidjson 的两倍以上。
另外,co 2.0 用 Json
类表示 JSON 对象,json::Value
类表示 JSON 对象中的元素。json::Value
只是一个平凡类,仅包含它在 JSON 内存块中的索引位置。JSON 对象析构时,仅调用一次 Json 类的析构函数,而不会调用 json::Value 的析构函数。
其他
- 修复 co/log 中的嵌套 log bug。
- 修复一些全局静态变量相互依赖引起的 bug。
- co/log 日志时间增加毫秒。
- TaskSched 类重命名为 Tasked。
- co/time.h 新增 epoch::ms() 与 epoch::us(),用于获取自 EPOCH 开始的时间。
- co/os.h 新增 os::signal() 方法,设置信号处理函数。
- fastring 中新增 safe_clear() 方法。
- Json 中新增 safe_clear() 方法。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。