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

YAML:C++配置文件如使用(socket为例)?

基础概念

定义

  • 一种人类可读的数据序列化格式,语法简洁,适合配置文件和数据交换。
  • 支持键值对、列表、嵌套结构,通过缩进表示层级关系。

示例语法

server:  # 对象(字典)host: "127.0.0.1"  # 字符串值port: 8080         # 整数值enabled: true      # 布尔值protocols:         # 列表- http- https

使用前提?(虚拟机Ubuntu下)

下载与安装

首先必须要下载yaml-cpp

下载终端指令

sudo apt install libyaml-cpp-dev

YAML和yaml-cpp关系

  • YAML 是格式标准:定义了数据的表示方式(如键值对、列表、嵌套结构等)。
  • yaml-cpp 是解析工具:是针对 C++ 语言实现的 YAML 解析库,类似的还有 Python 中的PyYAML、Java 中的SnakeYAML等。
  • 类比:YAML 相当于 “HTML 格式标准”,而 yaml-cpp 相当于 “C++ 中的 HTML 解析器库”。

如何使用?

创建后缀为yaml的config.yaml文件

server:       # 顶层键(对象/字典)host: "127.0.0.1"  # 子键:服务器IP地址port: 8080         # 子键:服务器端口号
  • server 是一个对象(Object),相当于 C++ 中的 std::map 或 Python 中的 dict

  • host 和 port 是 server 对象的属性,分别存储字符串和整数类型的值

在C++文件中提取配置的步骤

#include <yaml-cpp/yaml.h>
#include <iostream>int main() {// 1. 加载YAML文件YAML::Node config = YAML::LoadFile("config.yaml");// 2. 提取server节点(YAML::Node类型)YAML::Node serverNode = config["server"];// 3. 从server节点中提取host和portstd::string host = serverNode["host"].as<std::string>();  // 提取字符串int port = serverNode["port"].as<int>();                  // 提取整数// 4. 打印结果(验证提取成功)std::cout << "服务器地址: " << host << std::endl;std::cout << "服务器端口: " << port << std::endl;return 0;
}

完整场景(socket套接字通信)

服务端yserver.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <yaml-cpp/yaml.h>  // 添加yaml-cpp头文件
#include<iostream>
using namespace std;
#define BUFFER_SIZE 1024int main() {int server_socket, client_socket;struct sockaddr_in server_addr, client_addr;socklen_t client_addr_len;char buffer[BUFFER_SIZE];char host[16] = {0};  // 使用C风格字符串保持原有结构int port = 0;// 从YAML文件读取配置try {//1.加载YAML文件YAML::Node config = YAML::LoadFile("config.yaml");const std::string& host_str = config["server"]["host"].as<std::string>();strncpy(host, host_str.c_str(), sizeof(host) - 1);port = config["server"]["port"].as<int>();} catch (const YAML::Exception& e) {fprintf(stderr, "YAML解析错误: %s\n", e.what());return EXIT_FAILURE;}// 创建套接字server_socket = socket(AF_INET, SOCK_STREAM, 0);if (server_socket == -1) {perror("套接字创建失败");exit(EXIT_FAILURE);}// 设置服务器地址信息server_addr.sin_family = AF_INET;server_addr.sin_addr.s_addr = inet_addr(host);server_addr.sin_port = htons(port);// 绑定地址和端口if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("Binding failed");exit(EXIT_FAILURE);}// 开始监听if (listen(server_socket, 5) == -1) {perror("Listring failed");exit(EXIT_FAILURE);}printf("Server listening on port %d\n", port);while (1) {// 接收客户端连接client_addr_len = sizeof(client_addr);client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_len);if (client_socket == -1) {perror("Accepting failed");exit(EXIT_FAILURE);}printf("Accepted connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));while (1) {// 接收数据int bytes_received = read(client_socket, buffer, BUFFER_SIZE);if (bytes_received <= 0) {printf("Client disconnected\n");close(client_socket);break;}buffer[bytes_received] = '\0';printf("接收的数据:%s", buffer);// 发送数据回客户端write(client_socket, buffer, bytes_received);}break;}cout<<"关闭套接字"<<endl;;close(server_socket);return 0;
}

客户端yclient.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <iostream>
#include <yaml-cpp/yaml.h>  // 添加yaml-cpp头文件
using namespace std;
#define BUFFER_SIZE 1024int main(int argc, char* argv[]) {int client_socket;struct sockaddr_in server_addr;char buffer[BUFFER_SIZE];char host[16] = {0};  // 使用C风格字符串保持原有结构int port = 0;// 从YAML文件读取配置try {//读取并解析当前当前目录下的config.yaml文件YAML::Node config = YAML::LoadFile("config.yaml");/*config["server"]:访问根节点下的 server 键,返回 YAML::Node。["host"]:继续访问 server 节点下的 host 键。as<std::string>():将该节点的值转换为 C++ 字符串(std::string)。*/const std::string& host_str = config["server"]["host"].as<std::string>();//将 C++ 字符串安全地转换为 C 风格字符串,防止因字符串过长导致数组溢出,确保字符串以 \0 结尾strncpy(host, host_str.c_str(), sizeof(host) - 1);//提取port字段port = config["server"]["port"].as<int>();} catch (const YAML::Exception& e) {fprintf(stderr, "YAML解析错误: %s\n", e.what());exit(EXIT_FAILURE);}cout<<host<<"  "<<port<<endl; // 创建套接字client_socket = socket(AF_INET, SOCK_STREAM, 0);if (client_socket == -1) {perror("套接字创建失败");exit(EXIT_FAILURE);}// 设置服务器地址信息server_addr.sin_family = AF_INET;server_addr.sin_port = htons(port);if (inet_pton(AF_INET, host, &server_addr.sin_addr) <= 0) {perror("无效地址");exit(EXIT_FAILURE);}// 连接服务器if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {perror("连接失败");exit(EXIT_FAILURE);}printf("连接服务端 at %s:%d\n", host, port);while (1) {// 输入发送的数据printf("发送数据 (or 'exit' to quit): ");fgets(buffer, BUFFER_SIZE, stdin);if (strcmp(buffer, "exit\n") == 0) {break;}// 发送数据给服务器write(client_socket, buffer, strlen(buffer));// 接收回传数据int bytes_received = read(client_socket, buffer, BUFFER_SIZE);buffer[bytes_received] = '\0';printf("从服务端重新传回的数据: %s", buffer);}close(client_socket);return 0;
}

终端编译yserver.cpp和yclient.cpp

tcy@tcy-virtual-machine:~/sy2$ g++ yclient.cpp -o yclient -lyaml-cpp
tcy@tcy-virtual-machine:~/sy2$ g++ yserver.cpp -o yserver -lyaml-cpp

运行结果

YAML优势

对于包含大量参数的网络程序(如支持 SSL 的服务器、多客户端连接池),YAML 的分层结构可将配置按功能模块分组(如networksecuritylogging),避免代码中出现冗长的参数列表。

YAML核心优势场景

场景优势体现
多人协作开发配置文件易读,减少沟通成本
频繁变更的配置无需编译即可修改,适合运维快速调整
复杂系统架构分层配置清晰组织参数,避免代码混乱
多环境部署不同环境配置隔离,降低部署错误风险
跨团队 / 跨语言协作统一配置格式,减少集成障碍

对比其他配置格式的劣势

  • 与 JSON 相比:YAML 语法更灵活,但解析速度略慢(实际应用中差异可忽略)。
  • 与 INI 相比:YAML 支持复杂数据结构和分层配置,INI 仅支持简单键值对。
  • 与环境变量相比:YAML 适合大量配置参数,环境变量适合少量敏感信息(如密码)。

相关文章:

  • STM32[笔记]--7.MDK5调试功能
  • STM32F407控制单个张大头闭环步进电机讲解与梯形加减速(HAL库)
  • 西门子S7-200 SMART PLC:小型自动化领域的高效之选
  • F5设备查看型号 Device Management -->Devices
  • 【力扣】回溯专题目录
  • 【Python基础】06 实战:视频压缩迷你脚本设计
  • 【图像处理基石】什么是摄影的数码味?
  • Linux内存泄露排查方案
  • 第27篇:SELinux安全增强机制深度解析与OpenEuler实践指南
  • 华为云Flexus+DeepSeek征文|基于Dify构建文本/图像/视频生成工作流
  • 港澳地区,海外服务器ping通可能是地区运营商问题
  • iOS 使用 SceneKit 实现全景图
  • 华为云Flexus+DeepSeek征文 | 华为云ModelArts Studio实战指南:创建高效的AingDesk知识库问答助手
  • HarmonyOS NEXT仓颉开发语言实战案例:图片预览器
  • PyQtNode Editor 第三篇创建节点(节点的定义)
  • 圆周石墨密封流体温度场MATLAB分析(微分求积法求解二维能量方程)
  • python中学物理实验模拟:瞬间推力与摩擦力作用下的物体运动
  • AC-DC-AC间接变频电源设计方案(工频50Hz→20KHz)
  • 【大模型】Query 改写常见Prompt 模板
  • Idea 项目远程开发 Remote Development