# as_common **Repository Path**: H-kernel/as_common ## Basic Information - **Project Name**: as_common - **Description**: 跨平台common代码库,支持Linux、windows、Android和IOS - **Primary Language**: C - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-03-18 - **Last Updated**: 2026-05-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # as_common — libcommon [![version](https://img.shields.io/badge/version-1.0.0-blue.svg)](https://gitee.com/H-kernel/as_common) [![license](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE) [![language](https://img.shields.io/badge/language-C%2FC%2B%2B11-orange.svg)](https://gitee.com/H-kernel/as_common) [![platform](https://img.shields.io/badge/platform-Linux%20%7C%20Windows%20%7C%20macOS%20%7C%20iOS%20%7C%20Android-lightgrey.svg)](https://gitee.com/H-kernel/as_common) [![build](https://img.shields.io/badge/build-passing-brightgreen.svg)](https://gitee.com/H-kernel/as_common) 一个面向 C/C++ 项目的跨平台共享工具库,提供网络服务、密码学、多线程、日志、ARQ 协议等基础能力。编译产物为 `libcommon.so`(动态库)和 `libcommon.a`(静态库),供其他项目直接链接使用。 **支持平台:** Linux(主要)、Windows、macOS、iOS、Android ## 版本信息 | 项目 | 说明 | |------|------| | 当前版本 | v1.0.0 | | C++ 标准 | C++11 | | C 标准 | C89/C99 | | 主分支 | `master` | | 开发分支 | `dev` | | 仓库地址 | https://gitee.com/H-kernel/as_common | --- ## 目录 - [工程结构](#工程结构) - [三层架构](#三层架构) - [模块说明](#模块说明) - [C 核心层](#c-核心层) - [C++ OOP 层](#c-oop-层) - [安全函数层](#安全函数层) - [使用示例](#使用示例) - [日志](#日志) - [URL 解析](#url-解析) - [密码学](#密码学) - [线程安全队列](#线程安全队列) - [线程与互斥锁](#线程与互斥锁) - [内存池](#内存池) - [定时器](#定时器) - [INI 配置文件](#ini-配置文件) - [TCP 网络服务](#tcp-网络服务) - [文件系统](#文件系统) - [安全字符串函数](#安全字符串函数) - [KCP / ARQ 协议](#kcp--arq-协议) - [构建](#构建) - [运行测试](#运行测试) - [头文件引入路径](#头文件引入路径) --- ## 工程结构 ``` as_common/ ├── inc/ │ ├── as_config.h # 平台检测宏 (ENV_LINUX / WIN32 / __APPLE__ 等) │ ├── as_basetype.h # 跨平台基础类型 (SOCKET, LONGLONG, 字节序) │ ├── as_common.h # 公共错误码与对齐宏 │ ├── c/ # C 核心层头文件 │ ├── cpp/ # C++ OOP 层头文件 │ └── sec/ # 安全函数层头文件 ├── src/ │ ├── c/ # C 核心层实现 │ ├── cpp/ # C++ OOP 层实现 │ └── sec/ # 安全函数层实现 ├── build/ │ ├── Makefile # 主库构建 │ └── test/ # 测试程序源码与构建 └── README_ARQ.md # KCP 协议详细文档 ``` --- ## 三层架构 | 层次 | 路径 | 语言标准 | 定位 | |------|------|----------|------| | C 核心层 | `inc/c/`, `src/c/` | C89/C99 | 平台抽象、底层算法与数据结构 | | C++ OOP 层 | `inc/cpp/`, `src/cpp/` | C++11 | 对 C 核心的面向对象封装 | | 安全函数层 | `inc/sec/`, `src/sec/` | C | 微软风格的边界检查安全替代函数 | --- ## 模块说明 ### C 核心层 #### 内存管理 | 头文件 | 说明 | |--------|------| | `as_alloc.h` | 堆内存分配封装(malloc/free 包装) | | `as_palloc.h` | 内存池分配器,减少碎片,适合高频临时分配 | #### 线程与同步 | 头文件 | 说明 | |--------|------| | `as_thread.h` | 跨平台线程创建(POSIX pthread + Windows) | | `as_mutex.h` | 跨平台互斥锁 | | `as_event.h` | 条件变量,用于线程间信号通知 | #### 密码学 | 头文件 | 说明 | |--------|------| | `as_md5.h` | MD5 哈希(16 字节摘要) | | `as_sha256.h` | SHA-256 哈希(32 字节摘要) | | `as_sha512.h` | SHA-512 哈希(64 字节摘要) | | `as_base64.h` | Base64 编解码 | | `as_http_digest.h` | HTTP Digest 认证(支持 MD5/SHA-256) | #### 数据结构 | 头文件 | 说明 | |--------|------| | `as_queue.h` | 侵入式队列(基于 `container_of`,零额外开销) | | `as_queue_safe.h` | 线程安全队列(互斥锁保护,生产者-消费者场景) | | `as_json.h` | cJSON DOM 解析器与序列化器 | #### 网络与协议 | 头文件 | 说明 | |--------|------| | `as_arq.h` | KCP 可靠 UDP 协议(ARQ),详见 [KCP / ARQ 协议](#kcp--arq-协议) | #### 文件系统 | 头文件 | 说明 | |--------|------| | `as_filesys.h` | 目录创建、文件 stat、目录树遍历、文件复制 | #### 工具类 | 头文件 | 说明 | |--------|------| | `as_string.h` | 字符串工具(trim、strsep、strdup) | | `as_url.h` | URL 解析(协议、主机、端口、路径、查询参数) | | `as_options.h` | 命令行选项解析 | | `as_time.h` | 时间获取与格式化 | | `as_daemon.h` | 进程守护化(daemon)支持 | | `as_dlfcn.h` | 动态库加载封装(dlopen/dlsym 跨平台) | | `as_last_error.h` | 最近错误码存取 | --- ### C++ OOP 层 #### 日志系统 | 头文件 | 说明 | |--------|------| | `as_log.h` | 主日志接口,后台线程异步写入,支持文件轮转 | #### 线程管理 | 头文件 | 说明 | |--------|------| | `as_thread_manage.h` | 线程池单例,负责监控线程健康状态 | | `as_task.h` | 任务基类,RAII 管理,支持启动 N 个工作线程 | | `as_synchronized.h` | 同步原语封装 | | `as_lock_guard.h` | RAII 锁守卫 | #### 网络服务 | 头文件 | 说明 | |--------|------| | `as_network_svr.h` | TCP/UDP 服务端,面向对象接口 | #### 配置管理 | 头文件 | 说明 | |--------|------| | `as_ini_config.h` | INI 文件解析(支持 section、key、value) | #### 队列与消息 | 头文件 | 说明 | |--------|------| | `as_queue_sync.h` | 同步阻塞队列 | | `as_msg_block.h` | 消息块,用于零拷贝消息传递 | #### 工具类 | 头文件 | 说明 | |--------|------| | `as_ring_cache.h` | 环形缓存 | | `as_timer.h` | 定时器(回调式,支持单次与周期触发,单例) | | `as_sys_stat.h` | 系统监控(CPU、内存、网络、磁盘) | | `as_mem.h` | 内存工具 | | `as_tinyxml2.h` | TinyXML2 XML 解析器封装 | --- ### 安全函数层 提供微软风格的边界检查安全替代函数,防止缓冲区溢出: ```c #include "securec.h" memcpy_s(dest, destSize, src, count); strcpy_s(dest, destSize, src); sprintf_s(buf, bufSize, fmt, ...); ``` 声明于 `securec.h` / `securectype.h`。 --- ## 使用示例 ### 日志 ```cpp #include "as_log.h" // 初始化(程序启动时调用一次) ASSetLogLevel(NULL, AS_LOG_INFO); // 设置最低输出级别 ASSetLogFile(NULL, "./logs/", "myapp"); // 日志目录与应用名 ASSetLogFileLengthLimit(NULL, 10); // 单文件最大 10 MB ASSetLogFileCountLimit(NULL, 5); // 最多保留 5 个日志文件 ASStartLog(NULL); // 启动后台日志线程 // 写日志(线程安全,非阻塞) AS_LOG(AS_LOG_INFO, "server started, port=%d", 8080); AS_LOG(AS_LOG_WARNING, "retry count=%d", retries); AS_LOG(AS_LOG_ERROR, "connect failed: %s", strerror(errno)); // 程序退出时 ASStopLog(NULL); ``` 日志级别从高到低:`AS_LOG_EMERGENCY`、`AS_LOG_ALERT`、`AS_LOG_CRITICAL`、`AS_LOG_ERROR`、`AS_LOG_WARNING`、`AS_LOG_NOTICE`、`AS_LOG_INFO`。 --- ### URL 解析 ```c #include "as_url.h" as_url_t url; as_init_url(&url); const char *raw = "http://user:pass@example.com:8080/api/v1?token=abc&page=2"; if (as_parse_url(raw, &url) == AS_ERROR_CODE_OK) { printf("protocol : %s\n", url.protocol); // http printf("username : %s\n", url.username); // user printf("host : %s\n", url.host); // example.com printf("port : %d\n", url.port); // 8080 printf("path : %s\n", url.path); // /api/v1 printf("args : %s\n", url.args); // token=abc&page=2 } // 遍历查询参数 as_url_arg_t arg; if (as_first_arg(&url, &arg) == AS_ERROR_CODE_OK) { do { printf(" %s = %s\n", arg.name, arg.value); } while (as_next_arg(&arg, &arg) == AS_ERROR_CODE_OK); } // 查找指定参数 as_url_arg_t token; if (as_find_arg(&url, "token", &token) == AS_ERROR_CODE_OK) { printf("token = %s\n", token.value); // abc } ``` --- ### 密码学 #### MD5 ```c #include "as_md5.h" // 快速计算(结果为 32 位十六进制字符串) char hex[33]; as_get_md5("hello world", hex); printf("MD5: %s\n", hex); // 流式计算(适用于大数据分段处理) as_md5_ctx ctx; as_md5_init(&ctx); as_md5_update(&ctx, data_part1, len1); as_md5_update(&ctx, data_part2, len2); unsigned char digest[16]; as_md5_final(digest, &ctx); ``` #### SHA-256 ```c #include "as_sha256.h" // 快速计算 char hex[65]; as_get_sha256("hello world", hex); printf("SHA256: %s\n", hex); // 一次性计算(原始字节) SHA256_HASH digest; as_sha256_calculate(data, data_len, &digest); // 流式计算 as_sha256_ctx ctx; as_sha256_init(&ctx); as_sha256_update(&ctx, data, len); SHA256_HASH result; as_sha256_final(&ctx, &result); ``` #### Base64 ```c #include "as_base64.h" const unsigned char input[] = "hello world"; unsigned int inlen = (unsigned int)strlen((char *)input); // 编码 char encoded[BASE64_ENCODE_OUT_SIZE(11) + 1]; int enc_len = as_base64_encode(input, inlen, encoded); encoded[enc_len] = '\0'; printf("Base64: %s\n", encoded); // aGVsbG8gd29ybGQ= // 解码 unsigned char decoded[BASE64_DECODE_OUT_SIZE(enc_len) + 1]; int dec_len = as_base64_decode(encoded, (unsigned int)enc_len, decoded); decoded[dec_len] = '\0'; printf("Decoded: %s\n", decoded); // hello world ``` --- ### 线程安全队列 适合多生产者 / 多消费者场景,内部使用互斥锁保护。 ```c #include "as_queue_safe.h" #include "as_time.h" as_safe_queue_t *queue = as_safe_queue_create(1024); /* 生产者 */ char *item = (char *)malloc(64); snprintf(item, 64, "message-%d", i); if (as_safe_queue_push_back(queue, item) != AS_ERROR_CODE_OK) { free(item); // 队列已满 } /* 消费者 */ void *data = NULL; if (as_safe_queue_pop_front(queue, &data) == AS_ERROR_CODE_OK) { printf("got: %s\n", (char *)data); free(data); } else { as_sleep(10); // 队列为空,等待 10ms } printf("size=%u / max=%u\n", as_safe_queue_size(queue), as_safe_queue_max(queue)); as_safe_queue_destory(queue); ``` --- ### 线程与互斥锁 ```c #include "as_thread.h" #include "as_mutex.h" static as_mutex_t *g_lock = NULL; static int g_counter = 0; void *worker(void *arg) { for (int i = 0; i < 1000; i++) { as_mutex_lock(g_lock); g_counter++; as_mutex_unlock(g_lock); } return NULL; } int main(void) { g_lock = as_create_mutex(); as_thread_t *t1 = NULL, *t2 = NULL; as_create_thread(worker, NULL, &t1, AS_DEFAULT_STACK_SIZE, 1 /*joinable*/); as_create_thread(worker, NULL, &t2, AS_DEFAULT_STACK_SIZE, 1); as_join_thread(t1); as_join_thread(t2); as_destory_thread(t1); as_destory_thread(t2); printf("counter = %d\n", g_counter); // 2000 as_destroy_mutex(g_lock); return 0; } ``` --- ### 内存池 适合生命周期明确、高频分配的场景,整个 pool 一次性释放,无需逐一 free。 ```c #include "as_palloc.h" // 创建 16 KB 的内存池 as_pool_t *pool = as_create_pool(AS_DEFAULT_POOL_SIZE); // 分配(零初始化) char *buf = (char *)as_pcalloc(pool, 256); int *nums = (int *)as_pcalloc(pool, 100 * sizeof(int)); // 不需要单独 free,直接销毁整个 pool as_destroy_pool(pool); ``` --- ### 定时器 ```cpp #include "as_timer.h" // 继承 ITrigger,实现回调 class HeartbeatTimer : public ITrigger { public: virtual void onTrigger(void *pArg, ULONGLONG ullScales, TriggerStyle enStyle) { printf("heartbeat fired, scale=%llu\n", ullScales); } }; as_timer timer; timer.init(100); // 时间精度:100 ms/刻度 timer.run(); HeartbeatTimer hb; // 每 3000ms(30 刻 × 100ms)触发一次,周期模式 timer.registerTimer(&hb, NULL, 30, enRepeated); // 5000ms 后单次触发 HeartbeatTimer once; timer.registerTimer(&once, NULL, 50, enOneShot); // 取消定时器 timer.cancelTimer(&hb); timer.exit(); ``` --- ### INI 配置文件 ```ini # config.ini [server] host = 0.0.0.0 port = 8080 [database] host = 127.0.0.1 port = 3306 name = mydb ``` ```cpp #include "as_ini_config.h" as_ini_config cfg; cfg.ReadIniFile("config.ini"); std::string host, port; cfg.GetValue("server", "host", host); // "0.0.0.0" cfg.GetValue("server", "port", port); // "8080" cfg.GetValue("database", "host", host); // "127.0.0.1" // 动态修改并保存 cfg.SetValue("server", "port", "9090"); cfg.SaveIniFile(); // 覆盖写回原文件 // 导出到另一个文件 cfg.ExportToFile("config.backup.ini"); ``` --- ### TCP 网络服务 ```cpp #include "as_network_svr.h" // 1. 继承 as_tcp_conn_handle 实现连接处理逻辑 class EchoConn : public as_tcp_conn_handle { public: virtual void handle_recv() { char buf[1024] = {0}; as_network_addr peer; int n = recv(buf, &peer, sizeof(buf), enAsyncOp); if (n > 0) { send(buf, (uint32_t)n, enSyncOp); // echo back } } virtual void handle_send() {} }; // 2. 继承 as_tcp_server_handle,在 accept 时创建连接对象 class EchoServer : public as_tcp_server_handle { public: virtual int32_t handle_accept(as_network_addr *pRemote, as_tcp_conn_handle *&pConn) { pConn = new EchoConn(); return AS_ERROR_CODE_OK; } }; // 3. 组装并启动 as_network_svr svr; svr.init(DEFAULT_SELECT_PERIOD, AS_FALSE, // 无 UDP AS_FALSE, // 无主动 TCP 客户端 AS_TRUE); // 有 TCP 服务端 svr.run(); as_network_addr listenAddr(8080, AF_INET); EchoServer echoSvr; svr.regTcpServer(&listenAddr, &echoSvr); ``` --- ### 文件系统 ```c #include "as_filesys.h" #include "as_time.h" // 递归创建目录 as_mkdir_full((unsigned char *)"/tmp/myapp/logs", 0755); // 检查路径类型 if (as_is_directory("/tmp/myapp") == AS_TRUE) { printf("is directory\n"); } // 获取文件元信息 as_file_stat_t st; if (as_fs_stat("/tmp/myapp/data.bin", &st) == AS_ERROR_CODE_OK) { printf("size = %ld bytes\n", (long)st.size); printf("mtime = %ld\n", (long)st.mtime); } // 复制文件 as_file_copy("/tmp/src.txt", "/tmp/dst.txt"); // 监控目录变化(Linux,inotify) static AS_BOOLEAN g_watching = AS_TRUE; int32_t on_change(AS_DIR_WATCH type, const char *name, void *userdata) { const char *events[] = {"", "CREATE", "DELETE", "MODIFY", "MOVEIN", "MOVEOUT", "ATTRIB"}; printf("[%s] %s\n", events[type], name); return 0; } as_file_dir_watch_t watcher = { on_change, NULL }; as_file_dir_watch("/tmp/myapp", &watcher, &g_watching); // 阻塞直至 g_watching = AS_FALSE ``` --- ### 安全字符串函数 ```c #include "securec.h" char dst[64]; // 安全复制(目标缓冲区大小必须传入,防止溢出) strcpy_s(dst, sizeof(dst), "hello world"); // 安全格式化 char msg[128]; sprintf_s(msg, sizeof(msg), "user=%s, age=%d", username, age); // 安全内存拷贝 memcpy_s(dst, sizeof(dst), src, src_len); // 返回值检查 errno_t err = strcat_s(dst, sizeof(dst), " appended"); if (err != EOK) { fprintf(stderr, "strcat_s failed: %d\n", err); } ``` --- ## KCP / ARQ 协议 KCP 是一个快速可靠 UDP 协议,以消耗 **10%~20% 额外带宽**为代价,换取比 TCP **低 30%~40% 的平均延迟**和低 3 倍的最大延迟。 - 纯算法实现,无任何系统调用 - 调用方持有 UDP socket,通过回调向 KCP 提供数据收发能力 - 时钟由外部传入,便于嵌入任意事件循环 ### 基本用法 ```c #include "as_arq.h" // 1. 创建 KCP 实例(conv 为双方协商的会话 ID) ikcpcb *kcp = ikcp_create(conv, user); // 2. 设置底层 UDP 发送回调 kcp->output = udp_output; // 3. 周期驱动(每 10ms 调用一次) ikcp_update(kcp, millisec); // 4. 将收到的 UDP 数据喂给 KCP ikcp_input(kcp, udp_buf, udp_len); // 5. 发送应用数据 ikcp_send(kcp, buf, len); // 6. 接收应用数据 ikcp_recv(kcp, buf, size); ``` ### 调优模式 ```c // 普通模式(兼顾吞吐量) ikcp_nodelay(kcp, 0, 40, 0, 0); // 极速模式(最低延迟) ikcp_nodelay(kcp, 1, 10, 2, 1); // 调整收发窗口(默认 32 个包) ikcp_wndsize(kcp, sndwnd, rcvwnd); // 最小 RTO(默认 100ms,极速模式 30ms,可设为 10ms) kcp->rx_minrto = 10; ``` 完整文档见 [README_ARQ.md](README_ARQ.md)。 --- ## 构建 ```bash # 构建动态库和静态库 cd build && make # 清理构建产物 cd build && make clean # 安装头文件和库(默认安装到 /usr/local//) cd build && make install # 指定安装路径 cd build && make install prefix=/custom/path ``` **构建产物:** - `build/libcommon.so` — 动态库 - `build/libcommon.a` — 静态库 **编译标准与编译选项:** - C++ 标准:C++11 - 编译选项:`-Wall -Wformat=2 -Wfloat-equal -Wshadow -Wconversion -fstack-protector-all` --- ## 运行测试 测试程序与主库**独立构建**,每个测试二进制直接链接所有库源文件,无需预先构建库。 ```bash # 构建全部测试 cd build/test && make # 构建并运行指定测试 cd build/test && make test_ipv6 && ./test_ipv6 cd build/test && make test_url && ./test_url cd build/test && make test_safe_queue && ./test_safe_queue cd build/test && make test_log && ./test_log cd build/test && make test_dir_watch && ./test_dir_watch # 清理测试产物 cd build/test && make clean ``` 测试源码位于 `build/test/test_*.cpp`。 --- ## 头文件引入路径 所有使用方必须包含以下路径: ```makefile CFLAGS += -I inc/ -I inc/c/ -I inc/cpp/ -I inc/sec/ ``` --- ## 平台检测 平台宏定义于 `inc/as_config.h`: | 宏 | 平台 | |----|------| | `ENV_LINUX` | Linux | | `WIN32` | Windows | | `__APPLE__` | macOS | | `TARGET_OS_IPHONE` | iOS | | `OS_ANDROID` | Android | 跨平台基础类型(`SOCKET`、`LONGLONG`、字节序)定义于 `inc/as_basetype.h`。 公共错误码与对齐宏定义于 `inc/as_common.h`。