跳到主要内容

连接故障排查

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根因解决
BadConnectionRejectedServer 没监听 4840确认 Server 进程已启动
BadCommunicationError网络不通 / 防火墙拦telnet host 4840, 关防火墙
BadTcpEndpointUrlInvalidURL 拼写错检查 opc.tcp://host:port
BadTcpServerTooBusyServer 连接数满复用 Session, 减少并发
BadSecurityModeRejectedMode 不被支持GetEndpoints 看实际支持
BadSecurityPolicyRejectedPolicy 不被支持Server 开启 Basic256Sha256
BadCertificateInvalid证书过期 / 未生效重新生成
BadCertificateUntrustedServer 没信任客户端客户端 .der 拷到 Server trusted/
BadCertificateUriInvalidSAN URI ≠ ApplicationUri重新生成证书时统一
BadCertificateHostNameInvalid连接 host ≠ SAN.DNS用 IP 连或加 DNS SAN
BadCertificateTimeInvalid时钟偏差 > ~10 分钟NTP 同步
BadIdentityTokenInvalidUserToken 字段缺失检查 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 直接看消息.


相关链接