プログラムの目標は、Websockets を介してメイン サーバーに接続し、可能な限り接続を維持することです (クライアント ウォッチドッグ)。
その間、Tasker はクライアントから Json を受信し (Server Behaviour)、それに応じて処理し、応答する必要があります。
これを実行するには、GLib のマルチスレッド メソッドと、ネットワーク部分の Libwebsockets ライブラリを使用します。
C Client/Server 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;
}
最後に、Tasker クライアントのスレッド ルーチン ループとスレッド ループの実行コード
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 にアップロードすることもできます。ヘルプやヒントをいただければ幸いです :)。