
串口服务器测试实战:用 C 语言通过 TCP 方式操作 Moxa NPort
在工业现场,大量设备仍然使用 RS-232/485/422 串口通信。但随着网络的普及,工程师们更希望用以太网来远程管理这些串口设备------串口服务器正是为此而生。它将串口数据透明地映射到 TCP/IP 网络上,让远程主机像操作网络端口一样操作串口。
本文以 Moxa NPort 串口服务器为例,介绍其在 TCP Server 模式下的工作原理,并提供一套完整的 C 语言测试工具,帮助在项目开发阶段快速验证串口服务器的连通性和数据收发是否正常。
一、串口服务器的三种网络模式
Moxa NPort 串口服务器通常支持三种网络通信模式:
| 模式 | 连接方向 | 特点 |
|---|---|---|
| TCP Server | 设备被动监听,等待客户端连接 | 适合集中采集,远程主机主动连入 |
| TCP Client | 设备主动连接远端服务器 | 适合现场设备向上推送数据 |
| UDP | 无连接,单向数据报 | 低延迟广播场景,允许少量丢包 |
三者的核心区别在于谁发起连接。选择哪种模式取决于网络架构------如果远程主机是控制中心,串口服务器放在现场,那么 TCP Server 模式是最自然的选择:主机按需连接,随时收发。
二、TCP Server 模式的工作流程
TCP Server 模式的通信流程非常清晰:
TCP 三次握手
远程主机(客户端) ──────────────► NPort(监听端口)
◄──────────────
建立连接
发送数据:客户端 ──TCP──► NPort ──串口──► 串口设备
接收数据:串口设备 ──串口──► NPort ──TCP──► 客户端
- NPort 在指定端口(默认 4001)监听,等待 TCP 连接
- 远程主机作为 TCP Client 主动发起连接
- 连接建立后,双向数据透明传输:TCP 数据 → 串口输出,串口输入 → TCP 回传
- 一个连接建立后,串口数据仅发送给该客户端
简单说:连上 TCP 端口,就等于连上了物理串口。
三、测试工具设计与实现
为了验证串口服务器工作是否正常,我们用 C 语言编写一个测试客户端,提供三种工作模式:
- 交互模式:手动输入数据,观察回显
- 单次发送模式:发送一条消息后退出
- 自动测试模式:循环发送多组测试数据,自动校验收发结果
3.1 项目结构
moxa-c-code/
├── config.h # 连接配置(默认IP、端口、缓冲区大小)
├── moxa_client.c # 主程序
├── Makefile # 构建脚本
3.2 连接配置
config.h 中定义了默认连接参数和缓冲区大小:
c
#define DEFAULT_IP "192.168.12.25"
#define DEFAULT_PORT 4001
#define RECV_BUF_SIZE 1024
#define SEND_BUF_SIZE 1024
IP 和端口同时支持命令行参数覆盖,无需修改代码即可适配不同环境。
3.3 核心:TCP 连接与收发
连接函数是整个程序的基础。创建 TCP 套接字后,通过 inet_pton 将 IP 地址转换为网络格式,再调用 connect 完成三次握手:
c
static int connect_to_moxa(const char *ip, int port)
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
// ... 省略错误处理 ...
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
inet_pton(AF_INET, ip, &addr.sin_addr);
connect(sockfd, (struct sockaddr *)&addr, sizeof(addr));
return sockfd;
}
3.4 交互模式:select 实现双工收发
交互模式下,程序需要同时监听键盘输入和网络数据。使用 select 实现 I/O 多路复用:
c
FD_SET(STDIN_FILENO, &readfds); // 监听键盘输入
FD_SET(sockfd, &readfds); // 监听网络数据
select(maxfd + 1, &readfds, NULL, NULL, &tv);
键盘输入的换行符 \n 自动转为 \r\n,符合串口通信惯例。
3.5 自动测试模式
这是验证串口服务器数据通道的关键功能。程序循环发送多组测试数据,等待回显,对比收发内容:
c
const char *test_msgs[] = {
"Hello Moxa",
"ABCABCABC",
"0123456789",
};
for (int i = 0; i < count; i++) {
send(sockfd, msg, len, 0); // 发送
int n = recv_buf(sockfd, buf, ..., 2000); // 等待回显(2秒超时)
memcmp(msg, buf, len) == 0 ? PASS : INFO; // 对比结果
}
测试完成后输出汇总报告:
===== Test Result =====
Total: 10 Passed: 10 Failed: 0 Timeout: 0
关于回显:如果串口设备的 TX 和 RX 短接(环回),数据会原样返回,测试结果为"echo matched"。如果连接了实际设备,返回数据可能不同,此时只要有数据返回即判定为通过。
四、使用方法
编译
bash
make
交互模式
bash
./moxa_client -i 192.168.12.25 -p 4001
连接后直接输入文字按回车发送,串口返回的数据会实时显示。按 Ctrl+C 退出。
单次发送
bash
./moxa_client -i 192.168.12.25 -p 4001 -m "hello"
发送一条消息后自动退出,适合脚本调用。
自动测试
bash
# 默认3轮测试
./moxa_client -i 192.168.12.25 -p 4001 -t
# 10轮压力测试
./moxa_client -i 192.168.12.25 -p 4001 -t -n 10
五、实测效果
连接串口服务器后的交互模式运行效果:
$ ./moxa_client -i 192.168.12.25 -p 4001
Connecting to 192.168.12.25:4001 ...
Connected.
Interactive mode. Type message and press Enter to send. Ctrl+C to quit.
hello
Sent 7 bytes: hello
Recv 7 bytes: hello
自动测试模式运行效果:
$ ./moxa_client -i 192.168.12.25 -p 4001 -t -n 3
===== Data Send/Recv Test (count=3) =====
[Test 1/3] Sending: "Hello Moxa"
Sent 10 bytes
Recv 10 bytes: "Hello Moxa"
PASS (echo matched)
[Test 2/3] Sending: "ABCABCABC"
Sent 9 bytes
Recv 9 bytes: "ABCABCABC"
PASS (echo matched)
[Test 3/3] Sending: "0123456789"
Sent 10 bytes
Recv 10 bytes: "0123456789"
PASS (echo matched)
===== Test Result =====
Total: 3 Passed: 3 Failed: 0 Timeout: 0
六、注意事项
- 网络连通性 :测试前确保主机与串口服务器在同一网段,或路由可达。可通过
ping 192.168.12.25先行验证。 - 端口配置:NPort 默认监听 4001 端口,管理端口为 966。确保在 NPort 管理界面中将串口模式配置为 TCP Server。
- 串口参数匹配:NPort 的串口波特率、数据位、校验位需与对端串口设备一致,否则数据会乱码。
- 连接数限制:TCP Server 模式默认只允许一个客户端连接。如果已有连接占用,新的连接会被拒绝。
- 超时断开:NPort 支持配置空闲超时时间,长时间无数据传输可能自动断开。
七、总结
串口服务器的 TCP Server 模式本质上就是一个串口到 TCP 的透明桥------连接 TCP 端口等于连接物理串口。理解了这个本质,测试就很简单了:连上去,发数据,看回显。
本文提供的 C 语言测试工具涵盖了交互调试和自动化测试两种场景,可以在项目初期快速验证硬件连通性,也可以集成到自动化测试流程中做长期可靠性验证。
参考链接: