学习open62541 --- [34] 保持连接

Client与Server是通过安全通道进行通信(可参阅官方文档Part 2),英文叫Secure Channel,
在这里插入图片描述
在Client的默认配置中,安全通道的超时时间是10分钟,超过10分钟后就会与Server断开连接,如下,
在这里插入图片描述
但是大部分情况下我们都想一直连着,是否断开由Client来决定。直观的方法是把这个超时时间改大点,但是治标不治本。经过本人查看源码,发现有个比较好的方法,下面简单描述一下。


保持连接方法

方法的原理就是Client在Server端添加一个订阅,然后每隔1秒钟Client向Server发送一个publish请求,server就会返回一个keep alive的response。详细操作可以参考这篇文章

Client代码如下,这里为了方便测试,把安全通道的超时时间改为10秒,


#include <stdlib.h>
#include "open62541.h"


UA_Boolean running = true;


static void stopHandler(int sign) {
    
    
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
    running = false;
}


int main(void) 
{
    
    
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);
    
    UA_Client *client = UA_Client_new();
    UA_ClientConfig *cc = UA_Client_getConfig(client);
    UA_ClientConfig_setDefault(cc);
  
    cc->secureChannelLifeTime = 10000; // 安全通道超时时间改为10s
    
    
    UA_StatusCode retval = UA_Client_connect(client, "opc.tcp://localhost:4840");
    if(retval != UA_STATUSCODE_GOOD) {
    
    
        UA_Client_delete(client);
        return (int)retval;
    }
    
    // ----------------------------- 添加订阅 --------------------------------
    UA_CreateSubscriptionRequest request = UA_CreateSubscriptionRequest_default();
    /* Force the server to send keep alive responses every second to trigger
     * the client to send new publish requests. Requests from the client
     * will make the server to change to the new SecurityToken after renewal.
     */
    request.requestedPublishingInterval = 1000; // publish间隔设置为1s
    request.requestedMaxKeepAliveCount = 1;
    UA_CreateSubscriptionResponse response = UA_Client_Subscriptions_create(client, request,
                                                                            NULL, NULL, NULL);

    UA_CreateSubscriptionResponse_clear(&response);
    // -----------------------------------------------------------------------
    
    
    while (running)
    {
    
    
        UA_Client_run_iterate(client, 0);
    }
    
    
    /* Clean up */
    UA_Client_delete(client); /* Disconnects the client internally */
    
    return EXIT_SUCCESS;
}

server端代码如下,

#include "open62541.h"

#include <signal.h>
#include <stdlib.h>

UA_Boolean running = true;

static void stopHandler(int sign) {
    
    
    UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "received ctrl-c");
    running = false;
}

int main(void) 
{
    
    
    signal(SIGINT, stopHandler);
    signal(SIGTERM, stopHandler);

    UA_Server *server = UA_Server_new();
    UA_ServerConfig_setDefault(UA_Server_getConfig(server));
    UA_StatusCode retval = UA_Server_run(server, &running);
    
    UA_Server_delete(server);
    
    return retval == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE;
}

如何组织工程以及编译链接就不说了,可以参考之前的系列文章,最后编译ok后,先运行Server,再运行Client,

Client这边的打印如下,
在这里插入图片描述
可以看到Client端每隔大约7.5秒会重新创建安全通道,而Server端这边会一直保持连接状态

为什么是7.5秒呢?因为UA_Client_run_iterate()会在0.75*secureChannelLifeTime时重新创建安全通道,更新SecurityToken,这个也是官方文档中规定的(官方文档Part 4)。
在这里插入图片描述


总结

本文主要讲述Client如何在安全通道的超时时间到达前自动重新创建安全通道,并保持和Server的连接。解决办法也是在源码里的测试用例里发现的。

如果有写的不对的地方,希望能留言指正,谢谢阅读。

猜你喜欢

转载自blog.csdn.net/whahu1989/article/details/107991510
34