
网络后端通信【免费下载链接】libhv 比libevent/libuv/asio更易用的网络库。A c/c network library for developing TCP/UDP/SSL/HTTP/WebSocket/MQTT/Redis client/server.项目地址https://gitcode.com/gh_mirrors/li/libhv点击查看免费下载本指南以 libhv 仓库中 docs/cn/hbase.md 文档为骨架结合 base/hbase.c 源码实现与 unittest/hbase_test.c 单元测试系统讲解 libhv 基础函数库hbase的四大类 API内存分配、字符串操作、文件与目录工具、随机数与配置解析。读完本文你将掌握每个函数的语义、边界行为与典型应用场景并能在自己的 C/C 项目中直接复用以替代手写轮子。hbase.h是 libhv 的基础模块base 目录中声明基础函数它不依赖任何网络或事件循环组件被 libhv 的日志、命令行解析、HTTP、MQTT 等模块广泛复用是所有上层功能的地基。从 base/README.md 可以看到base 目录中 base/hbase.h 与array.h、hatomic.h、hlog.h等并列共同构成 libhv 的公共基础设施。一、内存分配与释放带计数的安全封装hbase提供了一组与标准库同名同义的内存函数但额外增加了分配/释放计数便于排查内存泄漏。void* hv_malloc(size_t size); void* hv_realloc(void* oldptr, size_t newsize, size_t oldsize); void* hv_calloc(size_t nmemb, size_t size); void* hv_zalloc(size_t size); void hv_free(void* ptr); // 使用hv分配内存次数 long hv_alloc_cnt(); // 使用hv释放内存次数 long hv_free_cnt();从 base/hbase.c 的实现可以看到几个关键行为失败即退出hv_malloc、hv_realloc、hv_calloc、hv_zalloc在底层malloc返回NULL时会向stderr打印malloc failed!并exit(-1)避免空指针在高层代码中继续传播。hv_zalloc自动清零hv_zalloc在malloc后立即memset(ptr, 0, size)等价于calloc是 libhv 内部最常用的分配方式。hv_realloc的三参数签名与标准realloc不同它要求调用者额外传入oldsize。当newsize oldsize时会对新增的尾部区域清零保证扩展后的内存是干净的见 base/hbase.c。原子计数分配计数s_alloc_cnt与释放计数s_free_cnt使用hatomic_t原子变量维护base/hbase.c因此在多线程并发分配时hv_alloc_cnt()/hv_free_cnt()的统计是准确的。配套的调试宏定义在 base/hbase.h#define HV_ALLOC(ptr, size) // 分配并打印调用位置 #define HV_ALLOC_SIZEOF(ptr) // 按指针所指类型大小分配 #define HV_FREE(ptr) // 释放并将指针置 NULL #define HV_MEMCHECK // atexit 注册 hv_memcheck其中HV_FREE(ptr)在释放后会把指针置为NULL可有效防止悬空指针HV_MEMCHECK通过atexit注册hv_memcheck()程序退出时自动打印Memcheck alloc:N free:N当两个计数不相等时即可定位内存泄漏。此外STACK_OR_HEAP_ALLOC/HV_STACK_ALLOC系列宏实现了小对象用栈、大对象用堆的分配策略默认栈缓冲阈值为HV_DEFAULT_STACKBUF_SIZE 1024字节。二、字符串操作原地修改与安全拷贝1. 大小写转换与翻转char* hv_strupper(char* str); // 转大写 char* hv_strlower(char* str); // 转小写 char* hv_strreverse(char* str); // 翻转三个函数均为原地修改并返回原指针。从 base/hbase.c 可见大小写转换通过位运算*p ~0x20/*p | 0x20实现仅处理 ASCII 字母。2. 前后缀与包含判断bool hv_strstartswith(const char* str, const char* start); bool hv_strendswith(const char* str, const char* end); bool hv_strcontains(const char* str, const char* sub);hv_strstartswith逐字符比较当start指针走到结尾时返回true因此空前缀恒为真base/hbase.c。hv_strendswith先分别遍历求长度若str长度小于end直接返回false再逆序比对base/hbase.c。hv_strcontains本质就是strstr(str, sub) ! NULL。此外头文件中还提供了通配符匹配函数hv_wildcard_match(str, pattern)支持*匹配任意字符序列配合 unittest/hbase_test.c 中的断言可以看到典型用法assert(hv_wildcard_match(www.example.com, *.example.com)); assert(hv_wildcard_match(www.example.com, www.*.com)); assert(hv_wildcard_match(www.example.com, www.example.*));3. 安全的 strncpy / strncatchar* hv_strncpy(char* dest, const char* src, size_t n); char* hv_strncat(char* dest, const char* src, size_t n);这两个函数是 libhv 对strncpy/strncat的安全性修正。base/hbase.h 的注释点明了差异标准strncpy要求n sizeof(dest_buf) - 1hv_strncpy直接传n sizeof(dest_buf)函数内部循环条件为--n 0保证无论如何都会写入结尾的\0base/hbase.c。也就是说hv_strncpy永远不会产生非\0结尾的缓冲区杜绝了字符串未截断这一经典 C 陷阱。在!HAVE_STRLCPY环境下strlcpy被定义为hv_strncpy、strlcat被定义为hv_strncatbase/hbase.h可作为可移植替代。4. 字符查找与路径/文件名提取char* hv_strnchr(const char* s, char c, size_t n); // 前 n 个字符内查找 #define hv_strrchr_dot(str) strrchr(str, .) // 找最后一个点 char* hv_strrchr_dir(const char* filepath); // 找最后一个路径分隔符 const char* hv_basename(const char* filepath); // 取文件名 const char* hv_suffixname(const char* filename); // 取后缀hv_strnchr在限定的n个字符范围内查找避免越界base/hbase.c。hv_strrchr_dir在 Windows 上同时识别/与\\两种分隔符base/hbase.c实现了跨平台路径解析。hv_basename与hv_suffixname分别基于hv_strrchr_dir与hv_strrchr_dot实现hv_suffixname在无.时返回空字符串。实际调用场景很常见libhv 命令行解析模块 base/hmain.c 用hv_basename(argv[0])获取程序名HTTP 静态文件服务 examples/httpd/handler.cpp 与 http/HttpMessage.h 用hv_suffixname判断请求文件类型multipart 表单解析 http/http_content.cpp 用hv_basename从完整路径中提取上传文件名。三、文件与目录工具int hv_mkdir_p(const char* dir); // 等价 mkdir -p int hv_rmdir_p(const char* dir); // 等价 rmdir -p bool hv_exists(const char* path); bool hv_isdir(const char* path); bool hv_isfile(const char* path); bool hv_islink(const char* path); size_t hv_filesize(const char* filepath);hv_mkdir_p模拟mkdir -p语义若目录已存在返回EEXIST否则逐级创建各级子目录成功返回0底层mkdir失败返回EPERMbase/hbase.c。仓库自带的可直接运行示例 unittest/mkdir_test.c 展示了其用法// 命令行: mkdir_test /a/b/c/d const char* dir argv[1]; return hv_mkdir_p(dir);hv_rmdir_p模拟rmdir -p语义目录不存在返回ENOENT删除失败返回EPERM删除成功后会继续向上尝试删除空父目录直到遇到非空目录为止base/hbase.c。hv_exists/hv_isdir/hv_isfile分别基于access(path, 0)与stat的S_ISDIR/S_ISREG宏判断hv_islink在非 Windows 平台使用lstat的S_ISLNK判断base/hbase.c。hv_filesize直接读取stat的st_size字段返回文件字节数。四、可执行文件信息与运行目录char* get_executable_path(char* buf, int size); // 如 /usr/local/bin/httpd char* get_executable_dir(char* buf, int size); // 如 /usr/local/bin char* get_executable_file(char* buf, int size); // 如 httpd char* get_run_dir(char* buf, int size); // 如 /home/www/html这几个函数常用于服务程序的启动目录与配置文件定位。从 base/hbase.c 可以看到它们的平台实现差异Linux通过readlink(/proc/self/exe, ...)获取可执行文件绝对路径macOS通过_NSGetExecutablePath来自mach-o/dyld.h见 base/hbase.cWindows通过GetModuleFileName(NULL, ...)。get_executable_dir与get_executable_file内部先调用get_executable_path再用hv_strrchr_dir拆分目录与文件名get_run_dir则直接返回getcwd(buf, size)的当前工作目录。五、随机数与随机字符串int hv_rand(int min, int max); // [min, max] 闭区间随机整数 char* hv_random_string(char* buf, int len); // 随机字母数字字符串hv_rand内部以time(NULL)作为种子首次调用时初始化srandbase/hbase.c返回[min, max]闭区间内的整数且断言max min。hv_random_string从 62 个字符大写字母 小写字母 数字中随机抽取len个字符并在末尾补\0base/hbase.c。注意len是字符个数因此传入的缓冲区实际需要len 1字节容量。典型场景MQTT 客户端 mqtt/mqtt_client.c 在未指定client_id时用hv_random_string(cli-client_id, cid_len)自动生成客户端 ID。单元测试 unittest/hbase_test.c 中也有直接调用char buf[16] {0}; printf(hv_rand(10, 99) - %d\n, hv_rand(10, 99)); printf(hv_random_string(buf, 10) - %s\n, hv_random_string(buf, 10));六、配置解析三件套布尔、容量与时长这组函数专为配置文件与命令行参数的字符串解析设计也是 libhv 各模块读取配置的高频入口。1. hv_getboolean布尔语义归一化// 1 y on yes true enable 返回 true通常用于配置文件 bool hv_getboolean(const char* str);从 base/hbase.c 的实现看它按字符串长度分派单字符时1/y/Y为真两个字符时on为真三个字符时yes为真四个字符时true为真六个字符时enable为真。除单字符分支外均使用stricmp比较因此不区分大小写空串、NULL及一切其他值返回false。真实使用示例HTTP 服务器 examples/httpd/httpd.cpp 用它解析配置中的日志 fsync 开关examples/httpd/httpd.cpp 用它解析访问日志开关从而把yes/no/true/false/on/off/enable/1/0等常见写法统一处理。2. hv_parse_size复合容量解析// 1T2G3M4K5B ?B size_t hv_parse_size(const char* str);支持按字节单位叠加的容量字符串单位大小写均可K/k1024、M/m1024²、G/g1024³、T/t1024⁴未带单位的裸数字按字节处理。实现上逐字符扫描遇到单位时用移位n 10/20/30/40换算后累加base/hbase.c。unittest/hbase_test.c 给出了明确的验证assert(hv_parse_size(256) 256); assert(hv_parse_size(1K) 1024); assert(hv_parse_size(1G2M3K4B) 1*1024*1024*1024 2*1024*1024 3*1024 4);3. hv_parse_time复合时长解析// 1w2d3h4m5s ?s time_t hv_parse_time(const char* str);与hv_parse_size结构完全对称支持s秒、m分、h时、d天、w周五种单位裸数字按秒计换算关系见 base/hbase.c1m60s、1h3600s、1d86400s、1w604800s。测试断言assert(hv_parse_time(30) 30); assert(hv_parse_time(1m) 60); assert(hv_parse_time(1d2h3m4s) 1*24*60*60 2*60*60 3*60 4);这类解析让配置写法非常人性化例如timeout5m、maxsize2G无需在配置中写冗长的秒数或字节数。七、URL 解析hv_parse_url 与 hurl_tURL 解析是 HTTP 客户端的基础能力hbase提供了一个零拷贝的轻量级解析器int hv_parse_url(hurl_t* stURL, const char* strURL);hurl_t 的数据结构设计hurl_t定义在 base/hbase.h不复制字符串内容而是用(off, len)偏移对记录每个字段在原始字符串中的位置typedef enum { HV_URL_SCHEME, // 协议 HV_URL_USERNAME, // 用户名 HV_URL_PASSWORD, // 密码 HV_URL_HOST, // 主机 HV_URL_PORT, // 端口 HV_URL_PATH, // 路径 HV_URL_QUERY, // 查询参数 HV_URL_FRAGMENT, // 锚点 HV_URL_FIELD_NUM, } hurl_field_e; typedef struct hurl_s { struct { unsigned short off; unsigned short len; } fields[HV_URL_FIELD_NUM]; unsigned short port; // 解析出的端口号数值形式 } hurl_t;解析完成后通过strURL stURL-fields[HV_URL_SCHEME].off即可用%.*s精确打印对应片段。支持的完整格式为scheme:[//[user[:password]]host[:port]][/path][?query][#fragment]关键解析规则来自 base/hbase.c返回值成功返回0stURL或strURL为空返回-1URL 总长度超过 65535 返回-2。默认端口未显式写端口时http://默认80https://默认443。IPv6 支持以[开头的 host 按 IPv6 处理自动剥离方括号。多段解析依次分离scheme://、user:pswd、host:port、/path、?query、#fragment每一段都可能在 URL 中缺省。unittest/hbase_test.c 对 8 种 URL 形态带认证信息、带端口、仅路径等逐一断言字段长度与端口值是理解解析规则的最佳参考const char* test_urls[] { http://user:pswd[www.example.com]:80/path?query#fragment, http://user:pswdwww.example.com:80/path?query#fragment, http://user:pswdwww.example.com/path?query#fragment, http://www.example.com/path?query#fragment, http://www.example.com/path?query, http://www.example.com/path, www.example.com/path, /path, }; // 全部断言 stURL.port 80且各字段长度正确注意hurl_t字段类型为unsigned short因此单字段偏移/长度最大 65535这也与解析器end - begin 65535返回-2的限制相呼应。八、如何验证与使用单元测试与集成方式hbase的完整测试见 unittest/hbase_test.c涵盖随机数、布尔解析、通配符匹配、容量/时长解析、URL 解析五大类断言目录相关函数另有 unittest/mkdir_test.c 演示hv_mkdir_p。仓库通过 Makefile / CMake 组织构建运行单元测试时可参考 scripts/unittest.sh 与 unittest/CMakeLists.txt 了解测试的构建与执行方式。使用上只要#include hbase.h即可获得上述全部能力。这些函数被 libhv 各模块广泛依赖例如日志模块对配置开关的处理examples/httpd/httpd.cpp静态文件服务器按后缀返回 Content-Typeexamples/httpd/handler.cppMQTT 客户端自动生成 Client IDmqtt/mqtt_client.c命令行解析器从argv[0]提取程序名base/hmain.c。总结hbase是 libhv 的瑞士军刀式基础函数库内存层提供带失败保护与原子计数的分配器及HV_MEMCHECK泄漏检测机制字符串层提供原地大小写/翻转、前后缀判断、通配符匹配和保证\0结尾的安全拷贝文件层提供跨平台路径拆分、mkdir -p/rmdir -p语义与文件属性查询配置层提供人性化的布尔、容量、时长字符串解析URL 层提供零拷贝的轻量级解析器。这些函数语义明确、有源码实现与单元测试双重背书非常适合在自有项目中作为可移植的基础工具直接复用。赞分享网络后端通信【免费下载链接】libhv 比libevent/libuv/asio更易用的网络库。A c/c network library for developing TCP/UDP/SSL/HTTP/WebSocket/MQTT/Redis client/server.项目地址https://gitcode.com/gh_mirrors/li/libhv点击查看免费下载相关推荐libhv网络库API完全指南libhv网络库API完全指南 1. 事件循环与基础功能 核心概念 libhv采用事件驱动模型通过 hloop_t 实现跨平台的IO多路复用epoll/k网络通信后端异步编程cudf pylibcudf 字符串 API 详解strip 函数去除字符串首尾字符的完整指南cudf pylibcudf 字符串 API 详解strip 函数去除字符串首尾字符的完整指南 本文围绕 cudf 仓库中 pylibcudf strip A数据分析数据工程机器学习Luau内置函数库完全指南数学、字符串、表操作等Luau内置函数库完全指南数学、字符串、表操作等 Luau 是一种快速、小巧、安全且逐步类型化的嵌入式脚本语言源自 Lua。作为 Roblox 游戏开编程语言语言运行时编译器解释器上一篇MultipleWindow3dScene未来展望探索WebRTC和WebSocket的扩展可能性下一篇Predis位操作高级应用基于BITCOUNT/BITOP的用户行为分析系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考