搭建服务端
能做什么
app::Server 是被读的一方:它监听 TCP 或串口,接受 app::Client 的连接,用真实协议语义对外提供数据。
两种典型用途:
服务端由三部分组成:
最小完整示例
一个提供三相电压、电流、频率的模拟设备:
把它和客户端配对跑,就能完成一次完整的读取。
常用变体
端口传 0 让系统分配
local_port() 在 start_tcp 成功后返回实际监听端口;串口或停止后返回 0。测试代码里用这个避免固定端口冲突。
关联模式
start_tcp 的第三个参数决定服务端接受什么样的客户端:
详见TCP 连接。
服务端用 local_public 时客户端也要用 local_public(单方面配对会失败)。角色由 SessionOptions::role 决定,拨号方向由传输层决定,两者相互独立 —— 详见协议角色与拨号方向。
定期更新数据
服务端跑起来后可以在业务线程更新数据:
Device::set 是线程安全的,可以在运行中由业务线程调用。单次更新原子发布,但不承诺不同属性之间的事务一致性 —— 别指望"改完电压后电流一定同步"。
更新数组的一个元素
set_element 用非零索引(从 1 开始),只替换一个一级元素,不需要重发整个数组。整体属性用 set。
声明自定义对象
设备有厂家私有对象时,用 define 声明:
约束:
define只支持未收录的 OI,用标准 OI 会失败- 只支持普通只读属性,不支持方法或记录声明
- 类型声明后不能替换 —— 要改类型必须重建
Device - 不发布未设置的属性 ——
define之后不set,读到的是 DAR=4
define 声明的属性 writable 恒为 false,且 Device::set 是本地配置方法,与协议 SET 服务无关。
要让远端能写入,必须走服务层高级 API用 ObjectSchema 声明 writable = true 并挂 provider,Device::define 做不到。
串口服务端
bits_per_character 必须与实际端口配置一致(这里是 8E1 = 11 位)。填错会导致帧间隔计算错误,在低波特率长帧时表现为偶发粘帧或丢帧。
1.5 停止位会被拒绝。手动 RS-485 方向切换必须提供真实的 async_drain 回调,只有时间估算无法保证硬件时序。详见串口连接。
多个客户端共享一份数据
连接上限由 ServerOptions::max_connections 控制(默认 16)。串口只有一个会话 —— 串口不能设这个参数。
在诊断回调里停止服务
diagnostic 在服务器自己的工作线程执行。如果在回调里调 stop(),会等待当前线程结束 —— 死锁。用 request_stop():
请求与响应报文
服务端对外的报文与客户端请求一一对应,本文不重复帧示例。完整的读取报文见各数据类别页: