libwebsockets записывает все активные соединения после получения
Я играю с учебником libwebsockets, пытаясь сделать так, чтобы после получения сообщения от соединения по заданному протоколу он отправлял ответ всем активным соединениям, реализующим этот протокол. Я использовал функцию libwebsocket_callback_all_protocol
но он не делает то, что, я думаю, должен делать из своего имени (я не совсем уверен, что он делает из документации).
Цель состоит в том, чтобы открыть две веб-страницы и, когда информация отправляется с одной, результат будет передан обеим. Ниже мой код - вы увидите, что libwebsocket_callback_all_protocol
называется main (которая в настоящее время ничего не делает, я думаю....):
#include <stdio.h>
#include <stdlib.h>
#include <libwebsockets.h>
#include <string.h>
static int callback_http(struct libwebsocket_context * this,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason, void *user,
void *in, size_t len)
{
return 0;
}
static int callback_dumb_increment(struct libwebsocket_context * this,
struct libwebsocket *wsi,
enum libwebsocket_callback_reasons reason,
void *user, void *in, size_t len)
{
switch (reason) {
case LWS_CALLBACK_ESTABLISHED: // just log message that someone is connecting
printf("connection established\n");
break;
case LWS_CALLBACK_RECEIVE: { // the funny part
// create a buffer to hold our response
// it has to have some pre and post padding. You don't need to care
// what comes there, libwebsockets will do everything for you. For more info see
// http://git.warmcat.com/cgi-bin/cgit/libwebsockets/tree/lib/libwebsockets.h#n597
unsigned char *buf = (unsigned char*) malloc(LWS_SEND_BUFFER_PRE_PADDING + len +
LWS_SEND_BUFFER_POST_PADDING);
int i;
// pointer to `void *in` holds the incomming request
// we're just going to put it in reverse order and put it in `buf` with
// correct offset. `len` holds length of the request.
for (i=0; i < len; i++) {
buf[LWS_SEND_BUFFER_PRE_PADDING + (len - 1) - i ] = ((char *) in)[i];
}
// log what we recieved and what we're going to send as a response.
// that disco syntax `%.*s` is used to print just a part of our buffer
// http://stackru.com/questions/5189071/print-part-of-char-array
printf("received data: %s, replying: %.*s\n", (char *) in, (int) len,
buf + LWS_SEND_BUFFER_PRE_PADDING);
// send response
// just notice that we have to tell where exactly our response starts. That's
// why there's `buf[LWS_SEND_BUFFER_PRE_PADDING]` and how long it is.
// we know that our response has the same length as request because
// it's the same message in reverse order.
libwebsocket_write(wsi, &buf[LWS_SEND_BUFFER_PRE_PADDING], len, LWS_WRITE_TEXT);
// release memory back into the wild
free(buf);
break;
}
default:
break;
}
return 0;
}
static struct libwebsocket_protocols protocols[] = {
/* first protocol must always be HTTP handler */
{
"http-only", // name
callback_http, // callback
0, // per_session_data_size
0
},
{
"dumb-increment-protocol", // protocol name - very important!
callback_dumb_increment, // callback
0, // we don't use any per session data
0
},
{
NULL, NULL, 0, 0 /* End of list */
}
};
int main(void) {
// server url will be http://localhost:9000
int port = 9000;
const char *interface = NULL;
struct libwebsocket_context *context;
// we're not using ssl
const char *cert_path = NULL;
const char *key_path = NULL;
// no special options
int opts = 0;
// create libwebsocket context representing this server
struct lws_context_creation_info info;
memset(&info, 0, sizeof info);
info.port = port;
info.iface = interface;
info.protocols = protocols;
info.extensions = libwebsocket_get_internal_extensions();
info.ssl_cert_filepath = cert_path;
info.ssl_private_key_filepath = key_path;
info.gid = -1;
info.uid = -1;
info.options = opts;
info.user = NULL;
info.ka_time = 0;
info.ka_probes = 0;
info.ka_interval = 0;
/*context = libwebsocket_create_context(port, interface, protocols,
libwebsocket_get_internal_extensions,
cert_path, key_path, -1, -1, opts);
*/
context = libwebsocket_create_context(&info);
if (context == NULL) {
fprintf(stderr, "libwebsocket init failed\n");
return -1;
}
libwebsocket_callback_all_protocol(&protocols[1], LWS_CALLBACK_RECEIVE);
printf("starting server...\n");
// infinite loop, to end this server send SIGTERM. (CTRL+C)
while (1) {
libwebsocket_service(context, 50);
// libwebsocket_service will process all waiting events with their
// callback functions and then wait 50 ms.
// (this is a single threaded webserver and this will keep our server
// from generating load while there are not requests to process)
}
libwebsocket_context_destroy(context);
return 0;
}
2 ответа
У меня была такая же проблема, libwebsocket_write
на LWS_CALLBACK_ESTABLISHED
сгенерировать случайный segfault, поэтому, используя список рассылки, разработчик libwebsockets Энди Грин дал мне правильный путь: libwebsocket_callback_on_writable_all_protocol
, файл test-server/test-server.c
В исходном коде библиотеки показан пример использования.
libwebsocket_callback_on_writable_all_protocol(libwebsockets_get_protocol(wsi))
Он работал очень хорошо, чтобы уведомить все экземпляры, но он только вызывает метод записи во всех подключенных экземплярах, он не определяет данные для отправки. Вам нужно управлять данными самостоятельно. Пример исходного файла test-server.c
показать образец кольцевого буфера, чтобы сделать это.
http://ml.libwebsockets.org/pipermail/libwebsockets/2015-January/001580.html
Надеюсь, поможет.
Из того, что я могу быстро извлечь из документации, чтобы отправить сообщение всем клиентам, вам нужно где-то сохранить (в векторе, хэш-карте, массиве и т. Д.) struct libwebsocket * wsi
что у вас есть доступ, когда ваши клиенты подключаются.
Затем, когда вы получаете сообщение и хотите передать его, просто позвоните libwebsocket_write
на все wsi *
экземпляров.
Это то, что я бы сделал, в любом случае.