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

网络库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

相关文章:

  • systemback复制系统报错
  • 【Unity Shader编程】之让画面动起来
  • JVM虚拟机:内存结构、垃圾回收、性能优化
  • 深入理解Java单例模式:确保类只有一个实例
  • Java-IO流之打印流详解
  • MySQL基础(四)DML、数据表操作DDL操作
  • MAX3490
  • 关于双网卡优先级:有效跃点数的解析(设置值×2)
  • Levenberg-Marquardt算法详解和C++代码示例
  • 代驾数据库
  • Java逻辑运算符常见错误分析与规避指南
  • 使用 Python 和 HuggingFace Transformers 进行对象检测
  • 位运算(Bitwise Operations)深度解析
  • 基于J2EE架构的在线考试系统设计与实现【源码+文档】
  • 机器学习算法时间复杂度解析:为什么它如此重要?
  • C/C++ 中附加包含目录、附加库目录与附加依赖项详解
  • 波士顿房价预测(线性回归模型)
  • c++重点知识总结
  • VMware 安装 CentOS8详细教程 (附步骤截图)附连接公网、虚拟机yum源等系统配置
  • SQLAlchemy 中的 func 函数使用指南
  • 台州网站优化方案/推广普通话内容100字
  • 做转运网站/浙江网络科技有限公司
  • 百度收录网站但首页快照不更新/时事新闻最新
  • 安康做网站公司/直通车关键词怎么选 选几个
  • 微信网站怎么做/帮收款的接单平台
  • 子目录创建网站/2023近期舆情热点事件