In general, I connected to the web socket server and I need to send a request all the time to the web socket after a certain time. Here is the method that runs when the server sends a message.

int onmessage(wsclient *c, wsclient_message *msg) { json_object *message; message = json_tokener_parse(msg->payload); json_object *t, *s; json_object_object_get_ex(message, "t", &t); json_object_object_get_ex(message, "s", &s); fprintf(stderr, "Got new event %s\n", json_object_get_string(t)); if (strcmp(json_object_get_string(t), "READY") == 0) { // Нужно хендлить именно если заголовок ивента это READY. json_object *d = json_object_object_get(message, "d"); // Число, которое нужно отправить на сервер. json_object *hb_interval = json_object_object_get(d, "heartbeat_interval"); // Интервал, с которым нужно выполнять запрос. } return 0; } 

At every interval of hb_interval I need to send such a JSON string to maintain connection with the server.

 { "op": 1; "d": [тут должно быть число d]; } 

How can this be implemented so that the program sends a heartbeat request and at the same time continues to listen to the server for requests?

I use LibWSClient and JSON-C .

  • As part of its training recently faced the same challenge. I was advised to see either multithreading or fork (). fork () seemed like a pretty adequate solution. - Shadr
  • Not familiar with LibWSClient, but if you know the socket that its functions use to communicate with the server, then you better look at poll (or select ). Both expect some event with the given file descriptors and have a timeout. Perhaps some kind of analogue of these functions already exists in lib. - avp

1 answer 1

I looked at the LibWSClient sorts. I’ll probably keep my opinion on its quality
(at least I did not find any documentation on the link),
but the main thing for you is that reading and calling client handlers takes place in a separate thread.

Those. after calling libwsclient_run() you immediately continue working in main (if processing has been called from its thread). Therefore, you can immediately make a cycle to send your messages.

Unfortunately, all synchronization of actions with handlers will have to be done through global variables, since either the interface does not provide any other interface.

Those. you must have something like that

 volatile int done = 0, // global variables, set on close, error, etc can_send_message = 0; volatile long long msec_hb_interval, // не думаю, что json_object тут это хорошее решение message_d; // число, которое надо отправлять время от времени // libWSClient event handlers int onclose(wsclient *c) { done = 1; return 0; } int onmessage(wsclient *c, wsclient_message *msg) { ... json_object *d = json_object_object_get(message, "d"); // Число, которое нужно отправить на сервер. json_object *hb_interval = json_object_object_get(d, "heartbeat_interval"); set_globals_from_json(d, hb_interval); can_send_message = 1; ... } .... int main (int ac, char *av[]) { ... wsclient *c = libwsclient_new(...); ... libwsclient_run(c); while (!done) { if (time_to_send_my_message(msec_hb_interval)) send_my_message(c, message_d, other_my_data_for_message); } //blocks until run thread for client is done. libwsclient_finish(c); ... } 

And in time_to_send_my_message() you need to carefully program the cycle of waiting for the moment of sending with checking the variables done and can_send_message between can_send_message , for example, usleep() .

Pay attention to the volatile attribute for global variables that may vary in different threads.

  • Thank you, you gave me an idea how to implement. It turns out that it is not necessary to send heartbeat exactly at the received interval. However, I did not know about the streams, it helped me a lot! - Memer
  • By the way, be careful with signal processing when using this library. The point is that the signal handler can be called in any of the program threads (if it is not masked in it). Thus, recv() in a stream that is created in libwsclient_run() can easily be interrupted by any signal and return -1. However, such a situation is handled there as an error, leading to closing the socket and stopping the flow. To reliably process signals in such an architecture, they need to be masked (see man pthread_sigmask ), but there is no handler when creating a stream in this lib. - avp