当前位置: 首页 > ai >正文

网络库libhv介绍

      libhv是一个类似于libevent、libev、libuv的跨平台网络库,提供了更易用的接口和更丰富的协议,用来开发TCP/UDP/SSL/HTTP/WebSocket/MQTT 客户端/服务端。源码地址:https://github.com/ithewei/libhv,最新发布版本为v1.3.3,License为BSD-3-Clause。

      libhv特性

      (1).跨平台:Linux、Windows、macOS、Android、iOS、BSD、Solaris

      (2).高性能事件循环:网络IO事件、定时器事件、空闲事件、自定义事件、信号

      (3).TCP/UDP 客户端/服务端/代理

      (4).TCP支持心跳、重连、转发、多线程安全写入和关闭等功能

      (5).内置常见的拆包模式:固定包长、分界符、头部长度字段

      (6).RUDP支持:WITH_KCP

      (7).SSL/TLS支持:可选WITH_OPENSSL、WITH_GNUTLS或WITH_MBEDTLS

      (8).HTTP客户端/服务器支持:https http1/x http2 grpc

      (9).HTTP支持静态文件服务、目录服务、正向/反向代理服务、同步/异步API处理器

      (10).HTTP支持RESTful风格、路由、中间件、keep-alive长连接、chunked分块、SSE等功能

      (11).WebSocket服务端/客户端

      (12).MQTT客户端

      libhv在Windows上编译,build.sh内容如下:

#! /bin/bashif [ $# != 1 ]; thenecho "Error: requires one parameters:  Relese or Debug"echo "For example: $0 Debug"exit -1
fiif [ $1 != "Release"  ] && [ $1 != "Debug" ]; thenecho "Error: the sparameter can only be Release or Debug"exit -1
fimkdir -p build && cd buildcmake \-G"Visual Studio 17 2022" -A x64 \${cuda_options} \-DCMAKE_BUILD_TYPE=$1 \-DCMAKE_CONFIGURATION_TYPES=$1 \-DCMAKE_INSTALL_PREFIX=../install \..
cmake --build . --target install --config $1rc=$?
if [[ ${rc} != 0 ]]; thenecho -e "\033[0;31mError: there are some errors in the above operation, please check: ${rc}\033[0m"exit ${rc}
elseecho "build completed"
fi

      HTTP客户端测试代码如下:

int test_libhv_http_client()
{const std::string server_url{ "http://192.168.19.205:8080" };HttpRequest request{};request.method = HTTP_GET;request.url =  server_url + "/api/test1";hv::HttpClient client{};HttpResponse response{};if (auto ret = client.send(&request, &response); ret == 0) {auto j = hv::Json::parse(response.body);if (j.contains("time")) {std::cout << "server time: " << j["time"] << std::endl;} else {std::cerr << "Error: missing time field: " << response.body << std::endl;}} else {std::cerr << "Error: failed to request: " << ret << std::endl;}constexpr char image_name[]{ "../../../testdata/cat.jpg" };std::ifstream in_file(image_name, std::ios::binary | std::ios::ate); if (!in_file.is_open()) {std::cerr << "Error: fail to open file: " << image_name << std::endl;return -1;}size_t file_size = in_file.tellg();std::unique_ptr<unsigned char[]> data(new unsigned char[file_size]);in_file.seekg(0);in_file.read(reinterpret_cast<char*>(data.get()), file_size);auto base64_data = hv::Base64Encode(data.get(), file_size);hv::Json j = {{"image_name", image_name},{"image_data", base64_data},{"image_size", file_size}};HttpRequest request2{};request2.method = HTTP_POST;request2.url = server_url + "/api/test2";request2.body = j.dump();request2.headers["Content-Type"] = "application/json";request2.timeout = 2;HttpResponse response2{};if (auto ret = client.send(&request2, &response2); ret == 0) {if (response2.status_code == HTTP_STATUS_OK) {// 200hv::Json j = hv::Json::parse(response2.body);if (!j.contains("image_size") || !j.contains("image_time")) {std::cerr << "Error: missing image_size or image_time: " << response2.body << std::endl;return -1;}std::cout << "image was created at: " << j["image_time"] << ", image size: " << j["image_size"] << std::endl;} else {std::cerr << "status code: " << response2.status_code << ", status message: " << response2.status_message() << ", body: " << response2.body << std::endl;return -1;}} else {std::cerr << "Error: failed to send, error code: " << ret << std::endl;return -1;}return 0;
}

      执行结果如下图所示:

      HTTP服务端测试代码如下:

int test_libhv_http_server()
{namespace fs = std::filesystem;hv::HttpService router{};router.GET("/api/test1", [](const HttpContextPtr& ctx) {std::cout << "client: ip addr: " << ctx->ip() << ", port: " << ctx->port() << ", method: " << ctx->method() << std::endl;auto get_local_time = [] {auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());std::tm* tm = std::localtime(&time);std::stringstream buffer;buffer << std::put_time(tm, "%Y-%m-%d %H:%M:%S");return buffer.str();};hv::Json j = {{"status", "success"},{"time", get_local_time()}};return ctx->send(j.dump());});router.POST("/api/test2", [](const HttpContextPtr& ctx) {try {std::cout << "client: ip addr: " << ctx->ip() << ", port: " << ctx->port() << ", method: " << ctx->method() << std::endl;auto j = hv::Json::parse(ctx->body());if (!j.contains("image_name") || !j.contains("image_data") || !j.contains("image_size")) {ctx->setStatus(HTTP_STATUS_BAD_REQUEST);return ctx->send(R"({"error":"missing image_name or image_data or image_size"})");}auto data = hv::Base64Decode(j["image_data"].get<std::string>().c_str());if (data.length() != j["image_size"]) {ctx->setStatus(HTTP_STATUS_PRECONDITION_FAILED);return ctx->send(R"({"error":"data length mismatch"})");}fs::path image_path = j["image_name"].get<std::string>();auto image_name = image_path.filename();std::ofstream out_file(image_name.string(), std::ios::binary);out_file.write(data.data(), data.length());out_file.close();auto get_time = [](fs::file_time_type tp) {using namespace std::chrono;auto sctp = time_point_cast<system_clock::duration>(tp - fs::file_time_type::clock::now() + system_clock::now());auto tt = system_clock::to_time_t(sctp);std::tm* gmt = std::localtime(&tt); // UTC: std::gmtime(&tt);std::stringstream buffer;buffer << std::put_time(gmt, "%Y-%m-%d %H:%M:%S");return buffer.str();};auto image_time = get_time(fs::last_write_time(image_name));std::cout << "image was created at: " << image_time << std::endl;auto get_file_size = [](std::uintmax_t size) {float s1 = size / 1024. / 1024 / 1024;float s2 = size / 1024. / 1024;float s3 = size / 1024.;if (s1 > 1)return std::make_tuple(s1, std::string(" GB"));if (s2 > 1)return std::make_tuple(s2, std::string(" MB"));if (s3 > 1)return std::make_tuple(s3, std::string(" KB"));return std::make_tuple(static_cast<float>(size), std::string(" Bytes"));};auto [image_size, suffix] = get_file_size(static_cast<std::intmax_t>(fs::file_size(image_name)));std::cout << "image size: " << image_size << suffix << std::endl;ctx->setContentType(APPLICATION_JSON);hv::Json j2 = {{"status", "success"},{"image_time", image_time},{"image_size", std::format("{:.4f}{}", image_size, suffix)}};return ctx->send(j2.dump());} catch (const std::exception& e) {ctx->setStatus(HTTP_STATUS_INTERNAL_SERVER_ERROR);hv::Json j3 = { "error", e.what() };return ctx->send(j3.dump());}});hv::HttpServer server{};server.port = 8080;//server.worker_threads = 2;server.service = &router;//server.run(); // blockingserver.start(); // non-blockingwhile (true) {hv_delay(1000);}return 0;
}

      执行结果如下图所示:

      GitHub:https://github.com/fengbingchun/OpenSSL_Test

http://www.xdnf.cn/news/12492.html

相关文章:

  • Selenium自动化测试之弹窗处理
  • [Python学习日记-91] 并发编程之多线程 —— threading 模块、开启线程的方式、线程相关的其他方法
  • 腾讯加持,销售易 CRM 优势几何?
  • 本机无法远程别的计算机的方法
  • 自制喜悦字贴
  • QILSTE 精巧电子元件H4-108FO/5M解析
  • 观测云OaC能力升级,通过Terraform实现配置闭环
  • MySQL基础(一)介绍、下载及安装
  • w384药品管理系统的设计与实现
  • MySQL基础(三)DQL(Data Query Language,数据查询语言)
  • 【第一章:人工智能基础】01.Python基础及常用工具包-(1)Python语法与基础数据类型
  • 开源音乐播放器 MusicFree 项目介绍:自由、纯粹、高度自定义的听歌体验
  • 谷歌云代理商 | 游戏行业专属方案:谷歌云实时多人游戏服务器架构
  • STM32实战: CAN总线数据记录仪设计方案
  • 利用ProtoBuf 实现网络版通讯录
  • Vue基础(14)_列表过滤、列表排序
  • arcpy与扩展模块
  • 灵感枯竭?ai写小说生成器来帮忙
  • 深入理解数字音频:采样率、位深与量化
  • nuScenes 数据集及同类型自动驾驶数据集介绍
  • vue3 按钮级别权限控制
  • 车型库查询接口如何用Java进行调用?
  • 【机械视觉】Halcon—【十、实例—木头检测_充电宝检测_豆子检测】
  • python打卡44天
  • Linux 下的COW机制(copy-on-write)
  • python八股文算法:三数之和
  • 前端~三维地图(cesium)地图遮罩蒙层
  • 货运车辆在高速公路上发生故障,应如何设置警示标志?
  • 山洪径流过程及洪水淹没数值模拟
  • JDK21 虚拟线程原理剖析与性能深度解析