网络库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.pswp.cn/pingmian/83920.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

施耐德特价型号伺服电机VIA0703D31A1022、常见故障

⚙️ ‌一、启动类故障‌ ‌电机无法启动‌ ‌可能原因‌&#xff1a;电源未接通、制动器未释放、接线错误或控制器故障。‌解决措施‌&#xff1a; 检查电源线路及断路器状态&#xff1b;验证制动器是否打开&#xff08;带制动器型号&#xff09;&#xff1b;核对电机与控制器…

【Redis从入门到精通实战文章汇总】

&#x1f4da;博客主页&#xff1a;代码探秘者 ✨专栏&#xff1a;文章正在持续更新ing… ✅C语言/C&#xff1a;C&#xff08;详细版&#xff09; 数据结构&#xff09; 十大排序算法 ✅Java基础&#xff1a;JavaSE基础 面向对象大合集 JavaSE进阶 Java版数据结构JDK新特性…

MCP 技术完全指南:微软开源项目助力 AI 开发标准化学习

引言 在人工智能快速发展的今天&#xff0c;如何让 AI 模型与客户端应用程序之间建立标准化的交互机制&#xff0c;已成为开发者们亟待解决的关键问题。微软近期开源的 mcp-for-beginners 项目&#xff0c;为我们提供了一个系统性学习 Model Context Protocol (MCP) 的绝佳机会…

SQL进阶之旅 Day 20:锁与并发控制技巧

【JDK21深度解密 Day 20】锁与并发控制技巧 文章简述 在高并发的数据库环境中&#xff0c;锁与并发控制是保障数据一致性和系统稳定性的核心机制。本文作为“SQL进阶之旅”系列的第20天&#xff0c;深入探讨SQL中的锁机制、事务隔离级别以及并发控制策略。文章从理论基础入手…

Qt(part 2)1、Qwindow(菜单栏,工具栏,状态栏),铆接部件,核心部件 ,2、添加资源文件 3、对话框

1、Qwindow tips&#xff1a;1&#xff0c;首先为什么创建出的对象基本都是指针形式&#xff0c;个人觉得是对象树的原因&#xff08;自动释放内存&#xff09;&#xff0c;指针来访问成员函数->的形式。2&#xff0c;菜单栏只能一个的&#xff0c;放窗口基本Set&#xff0c…

一款“短小精悍的”手机录屏软件

这个时代&#xff0c;手机自带录屏功能已经不是什么稀奇的事情了&#xff0c;但是手机自带的录屏功能不都是完美的&#xff0c;无法静音录屏、、不能修改画质、不能剪辑、不能自定义水印......emmm.....貌似除了录屏就什么都不会 今天分享的这款软件——ADV屏幕录制汉化版&…

力扣HOT100之二分查找:153. 寻找旋转排序数组中的最小值

这道题是上一道题&#xff1a;33. 搜索旋转排序数组的前置题&#xff0c;有点没看懂力扣为什么要这样安排题目顺序&#xff0c;应该把这道题按排在前面才对啊。。。这道题的思路已经在上一道题的思路中说过了&#xff0c;这里就直接复制粘贴上一篇博客中的内容了。 我们阅读完题…

libiec61850 mms协议异步模式

之前项目中使用到libiec61850库&#xff0c;都是服务端开发。这次新的需求要接收服务端的遥测数据&#xff0c;这就涉及到客户端开发了。 客户端开发没搞过啊&#xff0c;挑战不少&#xff0c;但是人不就是通过战胜困难才成长的嘛。通过查看libiec61850的客户端API发现&#xf…

【 知你所想 】基于ernie-x1-turbo推理模型实现趣味猜心游戏

&#x1f31f; 项目特点 &#x1f916; 智能AI&#xff1a;基于文心一言大模型&#xff0c;具有强大的推理能力&#x1f3af; 实时思考&#xff1a;展示AI的思考过程&#xff0c;让你了解AI是如何推理的&#x1f3ae; 互动性强&#xff1a;通过简单的"是/否"问答&…

Excel 模拟分析之单变量求解简单应用

正向求解 利用公式根据贷款总额、还款期限、贷款利率&#xff0c;求每月还款金额 反向求解 根据每月还款能力&#xff0c;求最大能承受贷款金额 参数&#xff1a; 目标单元格&#xff1a;求的值所在的单元格 目标值&#xff1a;想要达到的预期值 可变单元格&#xff1a;变…

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…

【Qt】之【Get√】【Bug】通过值捕获(或 const 引用捕获)传进 lambda,会默认复制成 const

通过值捕获&#xff08;或 const 引用捕获&#xff09;传进 lambda&#xff0c;会默认复制成 const。 背景 匿名函数外部定义 QSet<QString> nameSet,需要传入匿名函数使用修改 connect(dlg, ..., [nameSet](...) {nameSet.insert(name); // ❌ 这里其实是 const QSet…

css元素的after制作斜向的删除线

<div class"price_div"></div>.price_div{position: relative; } ::after{content: ;position: absolute;left: 0;top: 50%;width: 100%;height: 2px;background: #FF186B;transform: rotate(-5deg); }

uniapp map组件的基础与实践

UniApp 中的 map 组件用于在应用中展示地图,并且支持在地图上添加标记、绘制线条和多边形等功能。以下是一些基本用法: 1. 基本结构 首先,确保你在页面的 .vue 文件中引入了 map 组件。以下是创建一个简单地图的基本代码结构: <template><view class="con…

深入理解PHP安全漏洞:文件包含与SSRF攻击全解析

深入理解PHP安全漏洞&#xff1a;文件包含与SSRF攻击全解析 前言 在Web安全领域&#xff0c;PHP应用程序的安全问题一直备受关注。本文将深入探讨两种常见的PHP安全漏洞&#xff1a;文件包含漏洞和服务器端请求伪造(SSRF)&#xff0c;帮助开发者理解漏洞原理、利用方式以及防…

MS358A 低功耗运算放大器 车规

MS358A 低功耗运算放大器 车规 产品简述 MS358A 是双通道运算放大器&#xff0c;具有低功耗、宽电源电压范围、高单位增益带宽的特性。在特定情况下&#xff0c;压摆率可以达到0.4V/μs 。每个通道的静态电流 (5V) 只有 430μA 。 MS358A输入共模范围可以到地&#xff0c;同时…

n8n + AI Agent:AI 自动化生成测试用例并支持导出 Excel

n8n + AI Agent:AI 自动化生成测试用例并支持导出 Excel 最终成果展示一、准备工作二、手把手搭建工作流第一步:创建手动触发器 (Chat Trigger)第二步:创建 AI Agent 节点第三步:为 AI Agent 植入 DeepSeek AI 模型第四步:解析AI的响应 (Code)第五步:生成Excel文件 (Conv…

5.1 HarmonyOS NEXT系统级性能调优:内核调度、I/O优化与多线程管理实战

HarmonyOS NEXT系统级性能调优&#xff1a;内核调度、I/O优化与多线程管理实战 在HarmonyOS NEXT的全场景生态中&#xff0c;系统级性能调优是构建流畅、高效应用的关键。通过内核调度精细化控制、存储与网络I/O深度优化&#xff0c;以及多线程资源智能管理&#xff0c;开发者…

​线性注意力 vs. 传统注意力:效率与表达的博弈新解

​核心结论​&#xff1a;线性注意力用计算复杂度降维换取全局建模能力&#xff0c;通过核函数和结构优化补足表达缺陷 一、本质差异&#xff1a;两种注意力如何工作&#xff1f; ​特性​传统注意力&#xff08;Softmax Attention&#xff09;线性注意力&#xff08;Linear At…

github中main与master,master无法合并到main

文章目录 遇到问题背景怎么做 遇到问题 上传 github 时候&#xff0c;发现传上去的是 master&#xff0c;但是 github 竟然还有一个 main 背景 github 采用 main 替代 master 作为主分支不是出于技术背景&#xff0c;而是出于 2020 年全球范围内兴起的 “Black Lives Matter…