• 使用 C++20 实现异步网络访问


    libfv 介绍

    libfv是一个极简异步HTTP库,支持tcp、HTTP1.1、websocket的客户端/服务器等功能,可以通过它轻易实现HTTP异步开发。如果你刚好喜欢C++20异步,那么libfv就是你的最佳选择

    文档地址:https://libfv.fawdlstty.com/zh_hans/

    注意:使用这个库之前,首先需要知道 co_await 关键字的作用

    • 推荐异步学习文档:使用 Async 和 Await 的异步编程,微软官方出品C#语言的异步教程,将async关键字省略,await关键字换成co_await,就和C++的几乎一样了
    • 推荐异步学习文档:stackless与await,如果想要深入了解co_await关键字的实现思路那么不可错过

    废话不多说,教大家如何使用。首先安装:

    vcpkg install fawdlstty-libfv
    
    • 1

    然后,就可以使用libfv啦。

    同步转异步

    libfv既然是异步HTTP库,那么使用网络功能首先需要在异步函数里调用。众所周知,main函数是同步函数,因此,我们需要在main函数里发起异步任务。我们此处同步方法转异步方法:

    #include <fv/fv.h>
    
    Task<void> async_func () {
    	// 后面会写到异步功能的代码,将其粘贴到此处就可以啦
    }
    
    int main () {
    	fv::Tasks::Init ();
    	fv::Tasks::RunAsync (async_func);
    	fv::Tasks::LoopRun ();
    	fv::Tasks::Release ();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    http client

    libfv有个非常棒的特性是,内部维护连接池。只要schema(http或https)、域名、端口都相同,那么连接会自动复用。这特性将极大降低高频客户端的连接维护成本。

    注:连接池在libfv 0.0.7版本开始支持。另外libfv的http客户端功能比此处介绍更强。详见文档

    fv::Response _r1 = co_await fv::Get ("https://t.cn");
    fv::Response _r2 = co_await fv::Post ("https://t.cn", fv::body_kv ("a", "1"), fv::body_kv ("b", "2"));
    
    • 1
    • 2

    websocket client

    接下来是websocket客户端。同样也非常简单。以下代码即实现websocket的发送,以及循环接收后续数据:

    std::shared_ptr<fv::WsConn> _conn = co_await fv::ConnectWS ("wss://t.cn/ws");
    co_await _conn->SendText ("hello", 5);
    while (true) {
    	auto [_data, _type] = co_await _conn->Recv ();
    	std::cout << _data << std::endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    http server

    客户端基本使用介绍完毕。下面说说服务器端。我们来实现一个http服务器端,简单的返回hello world的功能:

    fv::HttpServer _server {};
    _server.SetHttpHandler ("/hello", [] (fv::Request &_req) -> Task<fv::Response> {
    	co_return fv::Response::FromText ("hello world");
    });
    co_await _server.Run (8080);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    以上代码运行之后,浏览器里请求 http://127.0.0.1:8080/hello,即可看到效果。

    websocket server

    websocket服务器端其实就是http服务器端,只不过监听之后处理函数的处理步骤不同而已,区别就是,判断客户端是否为websocket连接,如果是,那么升级为websocket连接即可:

    fv::HttpServer _server {};
    _server.SetHttpHandler ("/ws", [] (fv::Request &_req) -> Task<fv::Response> {
    	if (_req.IsWebsocket ()) {
    		auto _conn = co_await _req.UpgradeWebsocket ();
    		while (true) {
    			auto [_data, _type] = co_await _conn->Recv ();
    			if (_type == fv::WsType::Text) {
    				co_await _conn->SendText (_data.data (), _data.size ());
    			} else if (_type == fv::WsType::Binary) {
    				co_await _conn->SendBinary (_data.data (), _data.size ());
    			}
    		}
    		co_return fv::Response::Empty ();
    	} else {
    		co_return fv::Response::FromText ("please use websocket");
    	}
    });
    co_await _server.Run (8080);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    后续客户端通过 ws://127.0.0.1:8080/ws 即可实现连接websocket服务器。

  • 相关阅读:
    前端面试题10.23
    Python高级二
    入职芯片开发部后,每天摸鱼之外的时间我们要做些什么呢
    [SQL-SERVER:数据库安全及维护]:MSSM工具进行附加还原备份等操作
    C++安装qt软件教程
    MSYS2介绍及工具安装
    JUC并发编程系列详解篇十五(公平锁VS非公平锁)
    【网络安全产品】---网闸
    设计模式原则——单一职责原则(SPS)
    Java 多线程(四):锁(二)
  • 原文地址:https://blog.csdn.net/fawdlstty/article/details/125539950