Попытка заменить мой код libwebsocket на Boost :: Beast

Я использую libwebsockets для подключения к веб-серверу с помощью программы C ++. Я могу подключиться. Но как мне это сделать в Boost :: Beast

// Setup our lws connection info
struct lws_client_connect_info ConnectInfo;
memset(&ConnectInfo, 0, sizeof(ConnectInfo));
ConnectInfo.context = Context;
ConnectInfo.address = Host.c_str();
ConnectInfo.port = Port;
ConnectInfo.path = Path.c_str();
ConnectInfo.origin = NULL;
ConnectInfo.protocol = Protocols[1].name;
ConnectInfo.ietf_version_or_minus_one = -1;
ConnectInfo.ssl_connection = UseSSL ? 1 : 0; // XXX: If you want to allow self-signed certs, change 1 to 2

std::string fullhost;
fullhost.append(Host).append(":").append(std::to_string(Port));
ConnectInfo.host = fullhost.c_str();

if (lws_client_connect_via_info(&ConnectInfo) == nullptr) {
Logger::Error("Unable to initialize connection!");
return;
}

Я попробовал это, но рукопожатие не работает. Удаление рукопожатия вызывает дальнейшую ошибку. Это простой фрагмент вызова веб-сокета (для простоты и тестирования) прямо из документации Boost :: Beast. Есть ли способ здесь, что бы изменить и синтаксис?

// The io_service is required for all I/O
boost::asio::io_service ios;

// These objects perform our I/O
tcp::resolver resolver{ ios };
websocket::stream<tcp::socket> ws{ ios };

// Look up the domain name
auto const lookup = resolver.resolve({ host, port });

// Make the connection on the IP address we get from a lookup
boost::asio::connect(ws.next_layer(), lookup);

// Perform the websocket handshake
ws.handshake(host, "/");

// Send the message
ws.write(boost::asio::buffer(std::string(text)));

// This buffer will hold the incoming message
boost::beast::multi_buffer buffer;

// Read a message into our buffer
ws.read(buffer);

// Close the WebSocket connection
ws.close(websocket::close_code::normal);

// If we get here then the connection is closed gracefully

// The buffers() function helps print a ConstBufferSequence
std::cout << boost::beast::buffers(buffer.data()) << std::endl;

Но пока код libwebconnect очищается, beast выдает ошибку при запросе рукопожатия. Соединение проходит.

Эта строка показывает:

std::cerr << "Error: " << e.what() << std::endl;

Ошибка: сбой рукопожатия при обновлении Websocket.

Есть ли какие-то другие настройки, которые нужно сделать, чтобы это работало? Я обнаружил, что примеры синхронизации и асинхронности следуют одной и той же начальной настройке, и я попробовал оба примера на животных.

Обновление 10/15: я решил немного углубиться в код того, что делал libwebsocket, вот что я обнаружил, я надеюсь, что это поможет.

/**
* lws_client_connect_via_info() - Connect to another websocket server
* \param ccinfo: pointer to lws_client_connect_info struct
*
*  This function creates a connection to a remote server using the
*  information provided in ccinfo.
*/
LWS_VISIBLE LWS_EXTERN struct lws *
lws_client_connect_via_info(struct lws_client_connect_info * ccinfo);

Реализация

LWS_VISIBLE struct lws *
lws_client_connect_via_info(struct lws_client_connect_info *i)
{
struct lws *wsi;
int v = SPEC_LATEST_SUPPORTED;
const struct lws_protocols *p;

if (i->context->requested_kill)
return NULL;

if (!i->context->protocol_init_done)
lws_protocol_init(i->context);

wsi = lws_zalloc(sizeof(struct lws), "client wsi");
if (wsi == NULL)
goto bail;

wsi->context = i->context;
/* assert the mode and union status (hdr) clearly */
lws_union_transition(wsi, LWSCM_HTTP_CLIENT);
wsi->desc.sockfd = LWS_SOCK_INVALID;

/* 1) fill up the wsi with stuff from the connect_info as far as it
* can go.  It's because not only is our connection async, we might
* not even be able to get ahold of an ah at this point.
*/

/* -1 means just use latest supported */
if (i->ietf_version_or_minus_one != -1 && i->ietf_version_or_minus_one)
v = i->ietf_version_or_minus_one;

wsi->ietf_spec_revision = v;
wsi->user_space = NULL;
wsi->state = LWSS_CLIENT_UNCONNECTED;
wsi->pending_timeout = NO_PENDING_TIMEOUT;
wsi->position_in_fds_table = -1;
wsi->c_port = i->port;
wsi->vhost = i->vhost;
if (!wsi->vhost)
wsi->vhost = i->context->vhost_list;

wsi->protocol = &wsi->vhost->protocols[0];

/* for http[s] connection, allow protocol selection by name */

if (i->method && i->vhost && i->protocol) {
p = lws_vhost_name_to_protocol(i->vhost, i->protocol);
if (p)
wsi->protocol = p;
}

if (wsi && !wsi->user_space && i->userdata) {
wsi->user_space_externally_allocated = 1;
wsi->user_space = i->userdata;
} else
/* if we stay in http, we can assign the user space now,
* otherwise do it after the protocol negotiated
*/
if (i->method)
if (lws_ensure_user_space(wsi))
goto bail;

#ifdef LWS_OPENSSL_SUPPORT
wsi->use_ssl = i->ssl_connection;
#else
if (i->ssl_connection) {
lwsl_err("libwebsockets not configured for ssl\n");
goto bail;
}
#endif

/* 2) stash the things from connect_info that we can't process without
* an ah.  Because if no ah, we will go on the ah waiting list and
* process those things later (after the connect_info and maybe the
* things pointed to have gone out of scope.
*/

wsi->u.hdr.stash = lws_malloc(sizeof(*wsi->u.hdr.stash), "client stash");
if (!wsi->u.hdr.stash) {
lwsl_err("%s: OOM\n", __func__);
goto bail;
}

wsi->u.hdr.stash->origin[0] = '\0';
wsi->u.hdr.stash->protocol[0] = '\0';
wsi->u.hdr.stash->method[0] = '\0';
wsi->u.hdr.stash->iface[0] = '\0';

strncpy(wsi->u.hdr.stash->address, i->address,
sizeof(wsi->u.hdr.stash->address) - 1);
strncpy(wsi->u.hdr.stash->path, i->path,
sizeof(wsi->u.hdr.stash->path) - 1);
strncpy(wsi->u.hdr.stash->host, i->host,
sizeof(wsi->u.hdr.stash->host) - 1);
if (i->origin)
strncpy(wsi->u.hdr.stash->origin, i->origin,
sizeof(wsi->u.hdr.stash->origin) - 1);
if (i->protocol)
strncpy(wsi->u.hdr.stash->protocol, i->protocol,
sizeof(wsi->u.hdr.stash->protocol) - 1);
if (i->method)
strncpy(wsi->u.hdr.stash->method, i->method,
sizeof(wsi->u.hdr.stash->method) - 1);
if (i->iface)
strncpy(wsi->u.hdr.stash->iface, i->iface,
sizeof(wsi->u.hdr.stash->iface) - 1);

wsi->u.hdr.stash->address[sizeof(wsi->u.hdr.stash->address) - 1] = '\0';
wsi->u.hdr.stash->path[sizeof(wsi->u.hdr.stash->path) - 1] = '\0';
wsi->u.hdr.stash->host[sizeof(wsi->u.hdr.stash->host) - 1] = '\0';
wsi->u.hdr.stash->origin[sizeof(wsi->u.hdr.stash->origin) - 1] = '\0';
wsi->u.hdr.stash->protocol[sizeof(wsi->u.hdr.stash->protocol) - 1] = '\0';
wsi->u.hdr.stash->method[sizeof(wsi->u.hdr.stash->method) - 1] = '\0';
wsi->u.hdr.stash->iface[sizeof(wsi->u.hdr.stash->iface) - 1] = '\0';

if (i->pwsi)
*i->pwsi = wsi;

/* if we went on the waiting list, no probs just return the wsi
* when we get the ah, now or later, he will call
* lws_client_connect_via_info2() below.
*/
if (lws_header_table_attach(wsi, 0) < 0) {
/*
* if we failed here, the connection is already closed
* and freed.
*/
goto bail1;
}

if (i->parent_wsi) {
lwsl_info("%s: created child %p of parent %p\n", __func__,
wsi, i->parent_wsi);
wsi->parent = i->parent_wsi;
wsi->sibling_list = i->parent_wsi->child_list;
i->parent_wsi->child_list = wsi;
}
#ifdef LWS_WITH_HTTP_PROXY
if (i->uri_replace_to)
wsi->rw = lws_rewrite_create(wsi, html_parser_cb,
i->uri_replace_from,
i->uri_replace_to);
#endif

return wsi;

bail:
lws_free(wsi);

bail1:
if (i->pwsi)
*i->pwsi = NULL;

return NULL;
}

1

Решение

Я нашел проблему / проблемы. Общая ошибка / исключение, которое я видел для рукопожатия, заставила меня долго разбираться в этом.

  1. Проблема была глупой, я не давал ей правильный путь, когда делал рукопожатие, как

/ API? Serverkey = defaultkey&маркер = eyJhbGciOiJIUzI1NiIsInR5

  1. У сервера была настройка тайм-аута, которая закрывала бы соединение WebSocket.

Я думал о том, почему сообщение об ошибке не очень наглядно. Прошу прощения за мое невежество, но для правильного сообщения об ошибке клиенту, такого как истек срок сеанса / нет действительных учетных данных и т. Д., Следует ли проверить повышение asio / beast или локальный сервер?

1

Другие решения

Других решений пока нет …