OPC UA 客户端 KeepAlive

OPC UA client KeepAlive

尊敬的 OPC UA 社区!

我想使用 OPC Foundation and MS Azure 中的示例为我们的软件开发 OPC UA 客户端。我担心这些例子之间的区别。在第一个示例中,使用 ReconnectHandler:

在 KeepAlive 失败后重新连接
        private void Client_KeepAlive(Session sender, KeepAliveEventArgs e)
        {
            if (e.Status != null && ServiceResult.IsNotGood(e.Status))
            {
                Console.WriteLine("{0} {1}/{2}", e.Status, sender.OutstandingRequestCount, sender.DefunctRequestCount);

                if (reconnectHandler == null)
                {
                    Console.WriteLine("--- RECONNECTING ---");
                    reconnectHandler = new SessionReconnectHandler();
                    reconnectHandler.BeginReconnect(sender, ReconnectPeriod * 1000, Client_ReconnectComplete);
                }
            }
        }

        private void Client_ReconnectComplete(object sender, EventArgs e)
        {
            // ignore callbacks from discarded objects.
            if (!Object.ReferenceEquals(sender, reconnectHandler))
            {
                return;
            }

            session = reconnectHandler.Session;
            reconnectHandler.Dispose();
            reconnectHandler = null;

            Console.WriteLine("--- RECONNECTED ---");
        }

第二个,会话断开并重新创建:

        private void StandardClient_KeepAlive(Session session, KeepAliveEventArgs e)
        {
            // ignore if we are shutting down
            if (ShutdownTokenSource.IsCancellationRequested == true)
            {
                return;
            }

            if (e != null && session != null && session.ConfiguredEndpoint != null && OpcUaClientSession != null)
            {
                try
                {
                    if (!ServiceResult.IsGood(e.Status))
                    {
                        Logger.Warning($"Session endpoint: {session.ConfiguredEndpoint.EndpointUrl} has Status: {e.Status}");
                        Logger.Information($"Outstanding requests: {session.OutstandingRequestCount}, Defunct requests: {session.DefunctRequestCount}");
                        Logger.Information($"Good publish requests: {session.GoodPublishRequestCount}, KeepAlive interval: {session.KeepAliveInterval}");
                        Logger.Information($"SessionId: {session.SessionId}");

                        if (State == SessionState.Connected)
                        {
                            MissedKeepAlives++;
                            Logger.Information($"Missed KeepAlives: {MissedKeepAlives}");
                            if (MissedKeepAlives >= OpcKeepAliveDisconnectThreshold)
                            {
                                Logger.Warning($"Hit configured missed keep alive threshold of {OpcKeepAliveDisconnectThreshold}. Disconnecting the session to endpoint {session.ConfiguredEndpoint.EndpointUrl}.");
                                session.KeepAlive -= StandardClient_KeepAlive;
                                Task t = Task.Run(async () => await DisconnectAsync());
                            }
                        }
                    }
                    else
                    {
                        if (MissedKeepAlives != 0)
                        {
                            // reset missed keep alive count
                            Logger.Information($"Session endpoint: {session.ConfiguredEndpoint.EndpointUrl} got a keep alive after {MissedKeepAlives} {(MissedKeepAlives == 1 ? "was" : "were")} missed.");
                            MissedKeepAlives = 0;
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex, $"Error in keep alive handling for endpoint '{session.ConfiguredEndpoint.EndpointUrl}'. (message: '{ex.Message}'");
                }
            }
            else
            {
                Logger.Warning("Keep alive arguments seems to be wrong.");
            }
        }

哪个例子是正确的?对于这些选项中的任何一个,服务器是否会丢弃对监控项的订阅?我能否依靠这些示例来创建可靠的客户端,还是缺少某些内容?

感谢您的帮助!

这是查看 Reference Client and Reference Server 实施的最佳方式(例如通过“UA 快速启动应用程序”解决方案),因为它们已通过认证。如有疑问,请参考:

来自ConnectServerCtrl

private void Session_KeepAlive(Session session, KeepAliveEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.BeginInvoke(new KeepAliveEventHandler(Session_KeepAlive), session, e);
        return;
    }

    try
    {
        // check for events from discarded sessions.
        if (!Object.ReferenceEquals(session, m_session))
        {
            return;
        }

        // start reconnect sequence on communication error.
        if (ServiceResult.IsBad(e.Status))
        {
            if (m_reconnectPeriod <= 0)
            {
                UpdateStatus(true, e.CurrentTime, "Communication Error ({0})", e.Status);
                return;
            }

            UpdateStatus(true, e.CurrentTime, "Reconnecting in {0}s", m_reconnectPeriod);

            if (m_reconnectHandler == null)
            {
                if (m_ReconnectStarting != null)
                {
                    m_ReconnectStarting(this, e);
                }

                m_reconnectHandler = new SessionReconnectHandler();
                m_reconnectHandler.BeginReconnect(m_session, m_reconnectPeriod * 1000, Server_ReconnectComplete);
            }

            return;
        }

        // update status.
        UpdateStatus(false, e.CurrentTime, "Connected [{0}]", session.Endpoint.EndpointUrl);
                        
        // raise any additional notifications.
        if (m_KeepAliveComplete != null)
        {
            m_KeepAliveComplete(this, e);
        }
    }
    catch (Exception exception)
    {
        ClientUtils.HandleException(this.Text, exception);
    }
}