TDengine C/C++ 连接器入门指南

TDengine C/C++ 连接器入门指南

概述

TDengine C/C++ 连接器是 TDengine 提供的官方客户端驱动程序,允许 C/C++ 开发人员连接 TDengine 集群并进行数据存储、查询等操作。本指南将帮助您快速上手 C/C++ 连接器的使用。

前置条件

在开始之前,请确保:

  1. 已安装 TDengine :需要安装 TDengine 客户端或服务端
  2. 开发环境:支持 C/C++ 开发的编译器(GCC、Clang、MSVC 等)
  3. 操作系统:Linux、Windows 或 macOS

第一步:安装和配置

1.1 安装 TDengine 客户端

根据您的操作系统,安装相应的 TDengine 客户端:

Linux (Ubuntu/Debian)

bash 复制代码
wget https://www.taosdata.com/assets-download/3.0/TDengine-client-3.x.x.x-Linux-x64.tar.gz
tar -xzvf TDengine-client-3.x.x.x-Linux-x64.tar.gz
cd TDengine-client-3.x.x.x && sudo ./install_client.sh

Windows

  • 下载并运行 TDengine 客户端安装程序
  • 默认安装路径:C:\TDengine

macOS

  • 下载并运行 TDengine 客户端安装程序
  • 默认安装路径:/usr/local/Cellar/tdengine (Cellar 名称随不同系统版本会变化)

1.2 验证安装

安装完成后,验证头文件和动态库的位置:

操作系统 头文件路径 动态库路径
Linux /usr/local/taos/include /usr/local/taos/driver/libtaos.so
Windows C:\TDengine\include C:\TDengine\driver\taos.dll
macOS /usr/local/include /usr/local/lib/libtaos.dylib

第二步:选择连接方式

TDengine 支持两种连接方式:

2.1 WebSocket 连接(推荐)

优点

  • 客户端和服务端版本无需完全匹配
  • 性能接近原生连接
  • 支持云服务和远程连接

使用场景:适合大多数应用场景,特别是云环境和跨版本场景

2.2 原生连接

优点

  • 功能最完整
  • 直接通信,延迟略低

限制

  • 客户端和服务端版本需要严格匹配(强烈建议版本一致)

使用场景:局域网环境且版本可控时

第三步:编写第一个程序

3.1 创建项目目录

bash 复制代码
mkdir tdengine_demo
cd tdengine_demo

3.2 编写代码(WebSocket 连接)

创建文件 demo.c

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include "taos.h"

int main() {
    // 1. 初始化环境(可选,taos_connect 会自动调用)
    taos_init();
    
    // 2. 设置连接方式为 WebSocket(必须在程序开始时调用一次)
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    
    // 3. 连接到 TDengine
    TAOS *taos = taos_connect(
        "localhost",    // 主机地址
        "root",         // 用户名
        "taosdata",     // 密码
        NULL,           // 数据库名(可选)
        0               // 端口,0 表示使用默认端口(WebSocket 为 6041)
    );
    
    // 4. 检查连接是否成功
    if (taos == NULL) {
        printf("连接失败:%s\n", taos_errstr(NULL));
        return -1;
    }
    
    printf("连接成功!\n");
    printf("客户端版本:%s\n", taos_get_client_info());
    printf("服务端版本:%s\n", taos_get_server_info(taos));
    
    // 5. 创建数据库
    TAOS_RES *res = taos_query(taos, "CREATE DATABASE IF NOT EXISTS test");
    if (taos_errno(res) != 0) {
        printf("创建数据库失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    printf("数据库创建成功!\n");
    taos_free_result(res);
    
    // 6. 使用数据库
    res = taos_query(taos, "USE test");
    if (taos_errno(res) != 0) {
        printf("使用数据库失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    taos_free_result(res);
    
    // 7. 创建超级表
    res = taos_query(taos, 
        "CREATE STABLE IF NOT EXISTS meters "
        "(ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) "
        "TAGS (location BINARY(64), groupId INT)"
    );
    if (taos_errno(res) != 0) {
        printf("创建超级表失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    printf("超级表创建成功!\n");
    taos_free_result(res);
    
    // 8. 插入数据
    res = taos_query(taos,
        "INSERT INTO d1001 USING meters TAGS('Beijing.Chaoyang', 1) "
        "VALUES (NOW, 10.2, 219, 0.32)"
    );
    if (taos_errno(res) != 0) {
        printf("插入数据失败:%s\n", taos_errstr(res));
    } else {
        printf("成功插入 %d 行数据\n", taos_affected_rows(res));
    }
    taos_free_result(res);
    
    // 9. 查询数据
    res = taos_query(taos, "SELECT * FROM meters");
    if (taos_errno(res) != 0) {
        printf("查询失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        taos_close(taos);
        return -1;
    }
    
    // 10. 获取字段信息
    int num_fields = taos_num_fields(res);
    TAOS_FIELD *fields = taos_fetch_fields(res);
    
    // 打印表头
    for (int i = 0; i < num_fields; i++) {
        printf("%s\t", fields[i].name);
    }
    printf("\n");
    
    // 11. 逐行获取查询结果
    TAOS_ROW row;
    while ((row = taos_fetch_row(res))) {
        int *lengths = taos_fetch_lengths(res);
        for (int i = 0; i < num_fields; i++) {
            if (row[i] == NULL) {
                printf("NULL\t");
            } else {
                // 根据字段类型打印数据
                switch (fields[i].type) {
                    case TSDB_DATA_TYPE_TIMESTAMP:
                        printf("%lld\t", *(int64_t *)row[i]);
                        break;
                    case TSDB_DATA_TYPE_INT:
                        printf("%d\t", *(int *)row[i]);
                        break;
                    case TSDB_DATA_TYPE_FLOAT:
                        printf("%.2f\t", *(float *)row[i]);
                        break;
                    case TSDB_DATA_TYPE_BINARY:
                    case TSDB_DATA_TYPE_NCHAR:
                        printf("%.*s\t", lengths[i], (char *)row[i]);
                        break;
                    default:
                        break;
                }
            }
        }
        printf("\n");
    }
    
    // 12. 释放结果集
    taos_free_result(res);
    
    // 13. 关闭连接
    taos_close(taos);
    
    // 14. 清理环境
    taos_cleanup();
    
    printf("程序执行完毕!\n");
    return 0;
}

3.3 编写代码(原生连接)

如果您要使用原生连接,只需将 WebSocket 版本的第 2 步注释掉即可:

c 复制代码
// 使用原生连接,不需要设置驱动类型
// taos_options(TSDB_OPTION_DRIVER, "websocket");  // 注释或删除此行

// 连接到 TDengine(使用默认原生端口 6030)
TAOS *taos = taos_connect(
    "localhost",
    "root",
    "taosdata",
    NULL,
    0  // 0 表示使用默认端口(原生连接为 6030)
);

3.4 编译程序

Linux/macOS

bash 复制代码
gcc demo.c -o demo -ltaos -I/usr/local/taos/include -L/usr/local/taos/driver

Windows (使用 MSVC)

cmd 复制代码
cl demo.c /I C:\TDengine\include /link C:\TDengine\driver\taos.lib

Windows (使用 MinGW)

bash 复制代码
gcc demo.c -o demo.exe -I C:/TDengine/include -L C:/TDengine/driver -ltaos

3.5 运行程序

Linux/macOS

bash 复制代码
# 如果提示找不到动态库,需要设置 LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/taos/driver:$LD_LIBRARY_PATH
./demo

Windows

cmd 复制代码
demo.exe

预期输出

复制代码
连接成功!
客户端版本:3.3.x.x
服务端版本:3.3.x.x
数据库创建成功!
超级表创建成功!
成功插入 1 行数据
ts              current voltage phase   location        groupId
1704528000000   10.20   219     0.32    Beijing.Chaoyang        1
程序执行完毕!

第四步:核心概念理解

4.1 连接对象 (TAOS)

  • TAOS 是数据库连接句柄,所有操作都基于此句柄
  • 通过 taos_connect() 创建,使用完毕后必须调用 taos_close() 释放

4.2 结果集 (TAOS_RES)

  • TAOS_RES 是执行 SQL 后返回的结果集
  • 无论是查询、插入还是 DDL 操作,都会返回结果集
  • 使用完毕后必须调用 taos_free_result() 释放

4.3 错误处理

TDengine 使用错误码机制:

c 复制代码
TAOS_RES *res = taos_query(taos, sql);

// 检查是否出错
if (taos_errno(res) != 0) {
    printf("错误码:%d\n", taos_errno(res));
    printf("错误信息:%s\n", taos_errstr(res));
    taos_free_result(res);
    return -1;
}

重要 :不能通过 taos_query() 返回 NULL 来判断失败,必须使用 taos_errno() 检查错误码。

4.4 数据类型映射

TDengine 类型 C 类型 说明
TIMESTAMP int64_t Unix 时间戳(毫秒/微秒/纳秒)
INT int32_t 32位整数
BIGINT int64_t 64位整数
FLOAT float 单精度浮点数
DOUBLE double 双精度浮点数
BINARY char[] 二进制字符串
NCHAR char[] (UTF-8) Unicode 字符串
BOOL int8_t 布尔值(0 或 1)
TINYINT int8_t 8位整数
SMALLINT int16_t 16位整数

第五步:常见操作示例

5.1 批量插入数据

c 复制代码
// 方式 1:多行 SQL 插入
const char *sql = 
    "INSERT INTO "
    "d1001 USING meters TAGS('Beijing.Chaoyang', 1) VALUES (NOW, 10.2, 219, 0.32) "
    "d1002 USING meters TAGS('Beijing.Haidian', 2) VALUES (NOW, 11.5, 220, 0.28) "
    "d1003 USING meters TAGS('Shanghai.Pudong', 3) VALUES (NOW, 12.1, 221, 0.35)";

TAOS_RES *res = taos_query(taos, sql);
if (taos_errno(res) == 0) {
    printf("成功插入 %d 行数据\n", taos_affected_rows(res));
}
taos_free_result(res);

5.2 聚合查询

c 复制代码
const char *sql = 
    "SELECT location, AVG(current), MAX(voltage), MIN(phase) "
    "FROM meters "
    "WHERE ts >= NOW - 1h "
    "GROUP BY location";

TAOS_RES *res = taos_query(taos, sql);
if (taos_errno(res) != 0) {
    printf("查询失败:%s\n", taos_errstr(res));
    taos_free_result(res);
    return -1;
}

TAOS_ROW row;
while ((row = taos_fetch_row(res))) {
    printf("位置:%s, 平均电流:%.2f, 最大电压:%d, 最小相位:%.2f\n",
           (char *)row[0],
           *(double *)row[1],
           *(int *)row[2],
           *(double *)row[3]);
}

taos_free_result(res);

5.3 数据订阅(流式处理)

c 复制代码
#include "taos.h"
#include <stdio.h>

int main() {
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    TAOS *taos = taos_connect("localhost", "root", "taosdata", "test", 0);
    
    // 创建 topic
    TAOS_RES *res = taos_query(taos, 
        "CREATE TOPIC IF NOT EXISTS topic_meters AS SELECT * FROM meters");
    taos_free_result(res);
    
    // 创建消费者
    tmq_conf_t *conf = tmq_conf_new();
    tmq_conf_set(conf, "group.id", "group1");
    tmq_conf_set(conf, "td.connect.user", "root");
    tmq_conf_set(conf, "td.connect.pass", "taosdata");
    tmq_conf_set(conf, "auto.offset.reset", "earliest");
    
    tmq_t *tmq = tmq_consumer_new(conf, NULL, 0);
    tmq_conf_destroy(conf);
    
    // 订阅 topic
    tmq_list_t *topic_list = tmq_list_new();
    tmq_list_append(topic_list, "topic_meters");
    tmq_subscribe(tmq, topic_list);
    tmq_list_destroy(topic_list);
    
    // 消费数据
    while (1) {
        TAOS_RES *message = tmq_consumer_poll(tmq, 1000);
        if (message) {
            TAOS_ROW row;
            while ((row = taos_fetch_row(message))) {
                printf("收到新数据\n");
                // 处理数据...
            }
            taos_free_result(message);
        }
    }
    
    // 取消订阅并关闭
    tmq_unsubscribe(tmq);
    tmq_consumer_close(tmq);
    taos_close(taos);
    return 0;
}

第六步:最佳实践

6.1 连接管理

c 复制代码
// 使用连接池(简单示例)
#define MAX_CONNECTIONS 10
TAOS *pool[MAX_CONNECTIONS];

void init_pool() {
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        pool[i] = taos_connect("localhost", "root", "taosdata", "test", 0);
    }
}

void destroy_pool() {
    for (int i = 0; i < MAX_CONNECTIONS; i++) {
        if (pool[i]) taos_close(pool[i]);
    }
}

6.2 错误处理模式

c 复制代码
int execute_sql(TAOS *taos, const char *sql) {
    TAOS_RES *res = taos_query(taos, sql);
    int code = taos_errno(res);
    
    if (code != 0) {
        fprintf(stderr, "SQL 执行失败:%s\nSQL:%s\n", 
                taos_errstr(res), sql);
        taos_free_result(res);
        return -1;
    }
    
    int affected = taos_affected_rows(res);
    taos_free_result(res);
    return affected;
}

6.3 资源管理

必须释放的资源

  1. 结果集:taos_free_result(res)
  2. 连接:taos_close(taos)
  3. 语句:taos_stmt_close(stmt)

推荐使用 RAII 模式(C++)

cpp 复制代码
class TaosConnection {
private:
    TAOS *taos;
    
public:
    TaosConnection(const char *host, const char *user, 
                   const char *pass, const char *db) {
        taos = taos_connect(host, user, pass, db, 0);
        if (!taos) throw std::runtime_error(taos_errstr(NULL));
    }
    
    ~TaosConnection() {
        if (taos) taos_close(taos);
    }
    
    TAOS* get() { return taos; }
};

6.4 性能优化

  1. 批量操作:一次插入多行数据,而不是逐行插入
  2. 使用参数绑定:避免 SQL 拼接,提高性能和安全性
  3. 合理设置缓冲区 :使用 taos_fetch_block() 批量获取数据
  4. 连接复用:避免频繁创建和销毁连接
c 复制代码
// 使用 taos_fetch_block 批量获取
TAOS_RES *res = taos_query(taos, "SELECT * FROM meters");
TAOS_ROW *rows;
int num_rows;

while ((num_rows = taos_fetch_block(res, &rows)) > 0) {
    for (int i = 0; i < num_rows; i++) {
        // 处理 rows[i]
    }
}

taos_free_result(res);

第七步:调试和故障排查

7.1 启用日志

c 复制代码
// 设置日志级别
taos_options(TSDB_OPTION_DEBUGFLAG, "135");  // 135 = DEBUG 级别

7.2 常见问题

问题 1:找不到动态库

bash 复制代码
# Linux/macOS
export LD_LIBRARY_PATH=/usr/local/taos/driver:$LD_LIBRARY_PATH

# Windows:将 C:\TDengine\driver 添加到系统 PATH

问题 2:连接失败

  • 检查服务是否启动:systemctl status taosd(Linux)
  • 检查端口是否开放:WebSocket 6041,原生连接 6030
  • 检查防火墙设置

问题 3:版本不匹配(原生连接)

  • 确保客户端和服务端版本一致
  • 或改用 WebSocket 连接方式

问题 4:字符编码问题

c 复制代码
// 设置字符集为 UTF-8
taos_options(TSDB_OPTION_CHARSET, "UTF-8");

7.3 性能分析

c 复制代码
#include <time.h>

clock_t start = clock();
TAOS_RES *res = taos_query(taos, sql);
clock_t end = clock();

double elapsed = (double)(end - start) / CLOCKS_PER_SEC;
printf("SQL 执行耗时:%.3f 秒\n", elapsed);

taos_free_result(res);

第八步:进阶主题

8.1 使用 CMake 构建项目

创建 CMakeLists.txt

cmake 复制代码
cmake_minimum_required(VERSION 3.10)
project(TDengineDemo C)

set(CMAKE_C_STANDARD 11)

# 查找 TDengine 库
find_library(TAOS_LIBRARY taos
    PATHS /usr/local/taos/driver /usr/local/lib
)

if(NOT TAOS_LIBRARY)
    message(FATAL_ERROR "TDengine library not found")
endif()

# 设置头文件路径
include_directories(/usr/local/taos/include)

# 添加可执行文件
add_executable(demo demo.c)

# 链接 TDengine 库
target_link_libraries(demo ${TAOS_LIBRARY})

构建:

bash 复制代码
mkdir build && cd build
cmake ..
make
./demo

8.2 多线程使用

c 复制代码
#include <pthread.h>

void *worker_thread(void *arg) {
    // 每个线程使用独立的连接
    TAOS *taos = taos_connect("localhost", "root", "taosdata", "test", 0);
    
    // 执行操作...
    
    taos_close(taos);
    return NULL;
}

int main() {
    taos_init();
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    
    pthread_t threads[10];
    for (int i = 0; i < 10; i++) {
        pthread_create(&threads[i], NULL, worker_thread, NULL);
    }
    
    for (int i = 0; i < 10; i++) {
        pthread_join(threads[i], NULL);
    }
    
    taos_cleanup();
    return 0;
}

注意TAOS 连接对象不是线程安全的,每个线程应使用独立的连接。

8.3 异步查询

c 复制代码
void async_callback(void *param, TAOS_RES *res, int code) {
    if (code == 0) {
        printf("异步查询成功\n");
        TAOS_ROW row;
        while ((row = taos_fetch_row(res))) {
            // 处理数据
        }
    } else {
        printf("异步查询失败:%s\n", taos_errstr(res));
    }
    taos_free_result(res);
}

int main() {
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    TAOS *taos = taos_connect("localhost", "root", "taosdata", "test", 0);
    
    // 发起异步查询
    taos_query_a(taos, "SELECT * FROM meters", async_callback, NULL);
    
    // 主线程继续执行其他任务
    sleep(1);  // 等待异步操作完成
    
    taos_close(taos);
    return 0;
}

第九步:完整示例项目

创建一个完整的监控数据采集程序:

项目结构

复制代码
tdengine_monitor/
├── CMakeLists.txt
├── include/
│   └── monitor.h
├── src/
│   ├── main.c
│   ├── database.c
│   └── collector.c
└── README.md

monitor.h

c 复制代码
#ifndef MONITOR_H
#define MONITOR_H

#include "taos.h"

// 初始化数据库
int init_database(TAOS *taos);

// 采集数据
int collect_metrics(TAOS *taos);

// 查询统计
int query_statistics(TAOS *taos);

#endif

database.c

c 复制代码
#include "monitor.h"
#include <stdio.h>

int init_database(TAOS *taos) {
    const char *sqls[] = {
        "CREATE DATABASE IF NOT EXISTS monitor",
        "USE monitor",
        "CREATE STABLE IF NOT EXISTS metrics "
        "(ts TIMESTAMP, cpu_usage FLOAT, mem_usage FLOAT, disk_io INT) "
        "TAGS (hostname BINARY(64), region BINARY(32))"
    };
    
    for (int i = 0; i < 3; i++) {
        TAOS_RES *res = taos_query(taos, sqls[i]);
        if (taos_errno(res) != 0) {
            fprintf(stderr, "执行失败:%s\n", taos_errstr(res));
            taos_free_result(res);
            return -1;
        }
        taos_free_result(res);
    }
    
    printf("数据库初始化成功\n");
    return 0;
}

collector.c

c 复制代码
#include "monitor.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int collect_metrics(TAOS *taos) {
    // 模拟采集数据
    float cpu = (float)(rand() % 100);
    float mem = (float)(rand() % 100);
    int disk_io = rand() % 10000;
    
    char sql[1024];
    snprintf(sql, sizeof(sql),
        "INSERT INTO server01 USING metrics TAGS('server01', 'beijing') "
        "VALUES (NOW, %.2f, %.2f, %d)",
        cpu, mem, disk_io);
    
    TAOS_RES *res = taos_query(taos, sql);
    int code = taos_errno(res);
    taos_free_result(res);
    
    if (code == 0) {
        printf("数据采集成功:CPU=%.2f%%, MEM=%.2f%%, DiskIO=%d\n", 
               cpu, mem, disk_io);
        return 0;
    }
    
    return -1;
}

int query_statistics(TAOS *taos) {
    const char *sql = 
        "SELECT hostname, AVG(cpu_usage), AVG(mem_usage), MAX(disk_io) "
        "FROM metrics "
        "WHERE ts >= NOW - 1h "
        "GROUP BY hostname";
    
    TAOS_RES *res = taos_query(taos, sql);
    if (taos_errno(res) != 0) {
        fprintf(stderr, "查询失败:%s\n", taos_errstr(res));
        taos_free_result(res);
        return -1;
    }
    
    printf("\n=== 最近 1 小时统计 ===\n");
    TAOS_ROW row;
    while ((row = taos_fetch_row(res))) {
        printf("主机:%s, 平均CPU:%.2f%%, 平均内存:%.2f%%, 最大磁盘IO:%d\n",
               (char *)row[0],
               *(double *)row[1],
               *(double *)row[2],
               *(int *)row[3]);
    }
    
    taos_free_result(res);
    return 0;
}

main.c

c 复制代码
#include "monitor.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    // 初始化
    taos_init();
    taos_options(TSDB_OPTION_DRIVER, "websocket");
    
    // 连接数据库
    TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
    if (taos == NULL) {
        fprintf(stderr, "连接失败:%s\n", taos_errstr(NULL));
        return -1;
    }
    
    printf("已连接到 TDengine\n");
    
    // 初始化数据库
    if (init_database(taos) != 0) {
        taos_close(taos);
        return -1;
    }
    
    // 持续采集数据(演示 10 次)
    for (int i = 0; i < 10; i++) {
        collect_metrics(taos);
        sleep(1);
    }
    
    // 查询统计
    query_statistics(taos);
    
    // 清理
    taos_close(taos);
    taos_cleanup();
    
    printf("程序结束\n");
    return 0;
}

编译运行:

bash 复制代码
mkdir build && cd build
cmake ..
make
./tdengine_monitor

总结

本指南涵盖了 TDengine C/C++ 连接器的核心概念和常用操作:

  1. 安装配置:安装客户端并验证环境
  2. 连接方式:WebSocket(推荐)和原生连接
  3. 基础操作:连接、查询、插入、关闭
  4. 高级特性:参数绑定、批量操作、数据订阅
  5. 最佳实践:错误处理、资源管理、性能优化
  6. 实战项目:完整的监控数据采集示例

获取帮助


关于 TDengine

TDengine 专为物联网IoT平台、工业大数据平台设计。其中,TDengine TSDB 是一款高性能、分布式的时序数据库(Time Series Database),同时它还带有内建的缓存、流式计算、数据订阅等系统功能;TDengine IDMP 是一款AI原生工业数据管理平台,它通过树状层次结构建立数据目录,对数据进行标准化、情景化,并通过 AI 提供实时分析、可视化、事件管理与报警等功能。

相关推荐
地球资源数据云1 天前
2019-2024年中国逐年10米分辨率最大值合成NDVI数据集
大数据·运维·服务器·数据库·均值算法
Databend1 天前
Databend 2025:海量数据 × AI 一体化底座,v1.3 即将发布
大数据·数据仓库
自燃人~1 天前
怎么优化慢SQL
数据库·sql
vyuvyucd1 天前
C++ vector容器完全指南
c++
liulilittle1 天前
XDP VNP虚拟以太网关(章节:三)
网络·c++·网络协议·信息与通信·通信·xdp
我先去打把游戏先1 天前
TCP、TLS、HTTP、HTTPS、MQTT、MQTTS几种网络协议的对比与解释
嵌入式硬件·mcu·物联网·网络协议·tcp/ip·http·aws
leiming61 天前
c++ find_if 算法
开发语言·c++·算法
yuanmenghao1 天前
自动驾驶中间件iceoryx - 内存与 Chunk 管理(三)
数据结构·c++·算法·链表·中间件·自动驾驶
天码-行空1 天前
【大数据环境安装指南】HBase集群环境搭建教程
大数据·linux·运维·hbase