连接故障排查
ua.Connect() 失败抛 OpcUaException, 看 ex.StatusCode 即可定位.
5 层排查 (从下到上)
1. TCP 层 — 网络通不通
ping <host>
telnet <host> 4840 # 或 nc -zv <host> 4840
不通 → 检查防火墙 / NAT / VPN. 跨机子先关防火墙试.
2. OpenSecureChannel 层 — 端口和端点能握手
先用最简组合 (None + Anonymous) 排除加密:
using var ua = new DarraOpcUa("opc.tcp://host:4840");
ua.Connect();
成功 → 网络 + Server 都 OK, 后续问题在加密 / 身份. 失败 → 看 StatusCode 速查表.
3. 端点协商层 — 客户端要求的 Mode/Policy 服务端是否支持
var endpoints = OpcUaDiscovery.GetEndpoints("opc.tcp://host:4840");
foreach (var ep in endpoints)
Console.WriteLine($"{ep.SecurityMode} | {ep.SecurityPolicyUri}");
只能用列表里实际出现的组合.
4. 证书层 — 双向互信
如果 None 能连, Sign / SignAndEncrypt 不行, 走 加密配置:
- 客户端证书 SAN.URI = ApplicationUri
- 服务端 trusted/ 包含客户端
.der - 时间同步 (偏差超 ~10 分钟拒)
5. Session 层 — 用户身份
new DarraOpcUa(url); // 匿名
new DarraOpcUa(url, username: "admin", password: "x"); // 用户名
BadIdentityTokenRejected → 服务端账号 / 密码不对.
BadUserAccessDenied → 账号有但无 ConnectSession 权限, 改服务端 ACL.
StatusCode 速查
| StatusCode | 根因 | 解决 |
|---|---|---|
BadConnectionRejected | Server 没监听 4840 | 确认 Server 进程已启动 |
BadCommunicationError | 网络不通 / 防火墙拦 | telnet host 4840, 关防火墙 |
BadTcpEndpointUrlInvalid | URL 拼写错 | 检查 opc.tcp://host:port |
BadTcpServerTooBusy | Server 连接数满 | 复用 Session, 减少并发 |
BadSecurityModeRejected | Mode 不被支持 | GetEndpoints 看实际支持 |
BadSecurityPolicyRejected | Policy 不被支持 | Server 开启 Basic256Sha256 |
BadCertificateInvalid | 证书过期 / 未生效 | 重新生成 |
BadCertificateUntrusted | Server 没信任客户端 | 客户端 .der 拷到 Server trusted/ |
BadCertificateUriInvalid | SAN URI ≠ ApplicationUri | 重新生成证书时统一 |
BadCertificateHostNameInvalid | 连接 host ≠ SAN.DNS | 用 IP 连或加 DNS SAN |
BadCertificateTimeInvalid | 时钟偏差 > ~10 分钟 | NTP 同步 |
BadIdentityTokenInvalid | UserToken 字段缺失 | 检查 username/password 不为空 |
BadIdentityTokenRejected | 用户不存在或密码错 | 服务端账号管理 |
BadUserAccessDenied | 用户无连接权限 | 服务端 ACL |
BadTimeout | 连接 / 握手超时 | 加 connectTimeoutMs |
打开调试日志
看握手哪一步出问题:
Logging.SetLevel(LogLevel.Debug);
Logging.OnLog += (level, msg) => Console.WriteLine($"[{level}] {msg}");
或环境变量 DARRA_OPCUA_LOG_LEVEL=Debug. 会打印 Hello / OpenSecureChannel / GetEndpoints / CreateSession / ActivateSession 每一步的 RequestId 和 StatusCode.
实在定位不到, Wireshark 抓 4840 端口, 内置 OPC UA dissector 直接看消息.
相关链接
- 加密配置 — Sign / SignAndEncrypt 实操
- 必要环境 — 网络 / NTP / Server 选择
- 基础知识 — 安全模型
- 快速开始 — 启用加密