我目前正在构建一个 C Tasker,该程序的目标是通过 Websockets 连接到主服务器并尽可能保持连接活动(客户端看门狗)。
同时,Tasker 应该能够从客户端(服务器行为)接收 Json,相应地处理它们并回答。
为此,我使用 GLib 的多线程方法和网络部分的 Libwebsockets 库。
C 客户端/服务器 Tasker 运行良好,因此下一步应该是:当与主服务器的连接丢失时,尝试“永远”重新连接,直到主服务器启动,或者在另一个主服务器上回退。
这里的问题是,当我切断与服务器的连接时,看门狗线程似乎忽略了重新连接。由于线程与 libwesockets 回调完全隔离。
以下是代码片段:
在Tasker Server init中调用Tasker Client
int janus_websockets_init(janus_transport_callbacks *callback, const char *config_path) {
if(g_atomic_int_get(&stopping)) {
return -1;
}
if(callback == NULL || config_path == NULL)
return -1;
gateway = callback;
Client_start()
塔斯克服务器配置
struct lws_context_creation_info info;
memset(&info, 0, sizeof info);
info.port = wsport;
info.iface = ip ? ip : interface;
info.protocols = wss_protocols;
info.extensions = NULL;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.gid = -1;
info.uid = -1;
info.options = 0;
/* Create the WebSocket context */
wss = lws_create_context(&info);
if(wss == NULL) {
ZETA_LOG(LOG_FATAL, "Error initializing libwebsockets...\n");
} else {
ZETA_LOG(LOG_INFO, "WebSockets server started (port %d)...\n", wspor\
t);
}
塔斯克客户端配置
整数
Client_start()
{
//* register the signal SIGINT handler */
struct lws_context_creation_info info;
memset(&info, 0, sizeof info);
info.port = CONTEXT_PORT_NO_LISTEN;
info.iface = NULL;
info.protocols = wss_protocols;
info.ssl_cert_filepath = NULL;
info.ssl_private_key_filepath = NULL;
info.extensions = lws_get_internal_extensions();
info.gid = -1;
info.uid = -1;
info.options = 0;
protocol.name = "janus-protocol";
protocol.callback = &ws_client_service_callback;
protocol.per_session_data_size = sizeof(struct session_data);
protocol.rx_buffer_size = 0;
protocol.id = 0;
protocol.user = NULL;
context = lws_create_context(&info);
Tasker 客户端看门狗线程调用
if (context == NULL) {
printf(KRED"[Main Service] context is NULL.\n"RESET);
return -1;
}
wsz = lws_client_connect(context, "xxx.xxx.xxx.xxx",5000, 0,
"/", "xxx.xxx.xxx.xxx:5000", NULL,
protocol.name, -1);
if (wsz == NULL) {
printf(KRED"[Main] wsi create error.\n"RESET);
return -1;
}
reco = false;
printf(KGRN"[Main] wsi create success.\n"RESET);
printf(KRED"[Main Service] %d\n", ConnOk, RESET);
keepAlive = g_thread_try_new("KeepAliveLoop", keep_alive_routine, context, NULL);
while(!dead)
lws_service(context, 50);
lws_context_destroy(context);
return 0;
}
Finnaly The Tasker Client 线程例程循环和线程循环执行代码
static void keep_alive_loop()
{
json_t *hb = NULL;
char *toto = NULL;
if (reco == true)
{
wsz = lws_client_connect(context, "xxx.xxx.xxx.xxx",5000, 0,
"/", "xxx.xxx.xxx.xxx:5000", NULL,
protocol.name, -1);
printf(KRED"[Main Service] UNDER LOOOOOOPING .\n"RESET);
reco = false;
return;
}
hb = json_object();
json_object_set_new(hb, "zetapush", json_string("keepalive"));
json_object_set_new(hb, "timeout", json_integer(8000));
toto = json_dumps(hb, 0);
websocket_client_keep_alive_write_back(hb);
lws_callback_on_writable(wsz);
}
static void *keep_alive_routine(void *data)
{
printf(KBRN"[pthread_routine] WATCHDOG READY AND ANGRY .\n"RESET);
g_timeout_add_seconds(8, keep_alive_loop, NULL);
alive_loop = g_main_loop_new(NULL, 0);
g_main_loop_run(alive_loop);
}
如果需要任何进一步的精度让我知道,我也可以上传到 github 以便更好地阅读,任何帮助或提示将不胜感激:)。