为什么我在使用 Boost 库时出现接受错误 "I'm missing websocket handshake connection field is missing the upgrade token"
Why do I have accept error when using Boost library saying "I'm missing websocket handshake connection field is missing the upgrade token"
我是使用 Boost 库的新手。
我目前正在尝试将 websocket 连接到本地托管的网页,但出现错误。
它一直抱怨 websocket 连接字段缺少升级令牌,我不知道这是怎么回事。
以下是与创建和连接 websocket 相关的代码。
void
fail(beast::error_code ec, char const* what)
{
std::cerr << what << ": " << ec.message() << endl;
throw std::runtime_error("fail");
}
// Echoes back all received WebSocket messages
session::session(tcp::socket&& socket, queue<PQN_DATA_PACKET *> *pQ)
: ws_(std::move(socket))
{
cycle_cnt = 0;
phase_cnt = 0;
pconnectionQ = pQ;
m_portion = 0;
}
// Get on the correct executor
void session::run()
{
cout << "TODO session for " << endl;
// We need to be executing within a strand to perform async operations
// on the I/O objects in this session. Although not strictly necessary
// for single-threaded contexts, this example code is written to be
// thread-safe by default.
net::dispatch(ws_.get_executor(),
beast::bind_front_handler(
&session::on_run,
shared_from_this()));
}
// Start the asynchronous operation
void session::on_run()
{
cout << "ON_RUN_SESSION" << endl;
// Set suggested timeout settings for the websocket
ws_.set_option(
websocket::stream_base::timeout::suggested(
beast::role_type::server));
// Set a decorator to change the Server of the handshake
ws_.set_option(websocket::stream_base::decorator(
[](websocket::response_type& res)
{
res.set(http::field::server,
std::string(BOOST_BEAST_VERSION_STRING) +
" websocket-server-async");
}));
// Accept the websocket handshake
ws_.async_accept(
beast::bind_front_handler(
&session::on_accept,
shared_from_this()));
}
void session::on_accept(beast::error_code ec)
{
cout << "ON_ACCEPT SESSION" << endl;
if (ec)
return fail(ec, "accept");
// Read a message
// do_read();
// boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
// const int size = 256;
// unsigned char pu8rawbuf[size];
// for (int i = 0; i < size; i++) {
// pu8rawbuf[i] = rand() % 256;;
// }
cout << "accept connection" << endl;
//m_portion = 0;
//m_count_objects = 0;
//m_itr_doc = jsonDocumentData.MemberBegin();
//m_itr_arr = m_itr_doc->value.Begin();
//m_is_end_file = false;
do_write();
}
void session::do_read()
{
// Read a message into our buffer
ws_.async_read(
buffer_,
beast::bind_front_handler(
&session::on_read,
shared_from_this()));
}
void session::on_read(
beast::error_code ec,
std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
// This indicates that the session was closed
if (ec == websocket::error::closed)
return;
if (ec)
fail(ec, "read");
// Echo the message
ws_.text(ws_.got_text());
// auto jv = parse_file("./input2.json");
// pretty_print(std::cout, jv);
std::string stringForSending = std::string("TEST");
std::cout << "SENDED\n";
ws_.async_write(
net::buffer(stringForSending),
beast::bind_front_handler(
&session::on_write,
shared_from_this()));
}
错误发生在 session::on_accept() 函数中。错误信息如下:
TODO session for
ON_RUN_SESSION
DO_ACCEPT LISTENER
DO_ACCEPT LISTENER END
ON_ACCEPT SESSION
accept: The WebSocket handshake Connection field is missing the upgrade token
terminate called after throwing an instance of 'std::runtime_error'
what(): fail
我正在将 websocket 连接到本地托管的 node.js 服务器,端口号当然匹配。
以下代码片段来自 websocket 客户端。
const connectToWebSocketServer = () => {
const socket = new WebSocket(WEB_SOCKET_URL)
socket.onopen = (event) => {
console.warn('websocket connection established', event)
if (WEBSOCKET_CONNECTION_DURATION) {
setTimeout(() => {
socket.close()
console.warn('websocket connection closed')
}, WEBSOCKET_CONNECTION_DURATION)
}
}
谁能知道我的问题是什么以及我该如何解决这个问题?
提前致谢!
我再次完成了您的示例 - 这次是
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <iostream>
#include <memory>
#include <queue>
namespace net = boost::asio;
namespace beast = boost::beast;
using net::ip::tcp;
using beast::error_code;
static void fail(error_code ec, std::string_view msg) {
std::cerr << msg << ": " << ec.message() << std::endl;
throw std::runtime_error("fail");
}
struct PQN_DATA_PACKET {
};
struct session : std::enable_shared_from_this<session> {
session(tcp::socket&& socket) : _socket(std::move(socket)) {}
void run()
{
std::cout << "TODO session for " << _socket.remote_endpoint()
<< std::endl;
}
private:
tcp::socket _socket;
};
using Queue = std::queue<PQN_DATA_PACKET*>;
struct listener : std::enable_shared_from_this<listener> {
net::io_context& _ioc;
tcp::acceptor _acceptor{_ioc};
Queue& _connectionQ;
listener(net::io_context& ioc, tcp::endpoint ep, Queue& connectionQ)
: _ioc(ioc)
, _acceptor(ioc, ep)
, _connectionQ(connectionQ)
{
}
// Start accepting incoming connections
void run() { do_accept(); }
void do_accept()
{
std::cout << "DO_ACCEPT LISTENER" << std::endl;
// The new connection gets its own strand
_acceptor.async_accept( //
net::make_strand(_ioc),
beast::bind_front_handler(&listener::on_accept,
shared_from_this()));
std::cout << "DO_ACCEPT LISTENER END" << std::endl;
}
void on_accept(beast::error_code ec, tcp::socket socket)
{
std::cout << "ON_ACCEPT LISTENER" << std::endl;
if (ec) {
fail(ec, "accept");
} else {
// Create the session and run it
std::make_shared<session>(std::move(socket) /*, _connectionQ*/)
->run();
}
// Accept another connection
do_accept();
}
};
struct server {
net::io_context _ioc;
Queue _connectionQ;
void run(tcp::endpoint ep, unsigned nthreads = 1) {
std::make_shared<listener>(_ioc, ep, _connectionQ) //
->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> v(nthreads);
for (auto& th : v)
th = std::thread([this] { _ioc.run(); });
for (auto& th : v)
if (th.joinable())
th.join();
}
};
int main() {
static uint16_t constexpr SERVER_PORT_NUMBER = 9797;
server srv;
srv.run({{}, SERVER_PORT_NUMBER}, 1);
}
然后我在节点中做了一个示例客户端:
#!/usr/bin/env node
var WebSocketClient = require('websocket').client;
var client = new WebSocketClient();
client.on('connectFailed', function(error) {
console.log('Connect Error: ' + error.toString());
});
client.on('connect', function(connection) {
console.log('WebSocket Client Connected');
connection.on('error', function(error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function() {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
}
});
function sendNumber() {
if (connection.connected) {
var number = Math.round(Math.random() * 0xFFFFFF);
connection.sendUTF(number.toString());
console.log("Sending: '" + number.toString() + "'");
setTimeout(sendNumber, 1000);
}
}
sendNumber();
});
client.connect('ws://localhost:9797/', '');
我可以 运行 他们很好:
./sotest & npm install websocket && nodejs ./test.js
版画
[1] 14461
DO_ACCEPT LISTENER
DO_ACCEPT LISTENER END
added 18 packages, and audited 19 packages in 699ms
found 0 vulnerabilities
ON_ACCEPT LISTENER
TODO session for
DO_ACCEPT LISTENER
DO_ACCEPT LISTENER END
accept connection
WebSocket Client Connected
Sending: '7599795'
Received: '7599795'
Sending: '3553782'
Received: '3553782'
Sending: '13810406'
Received: '13810406'
Sending: '12580747'
Received: '12580747'
Sending: '3757113'
Received: '3757113'
等等
我是使用 Boost 库的新手。
我目前正在尝试将 websocket 连接到本地托管的网页,但出现错误。
它一直抱怨 websocket 连接字段缺少升级令牌,我不知道这是怎么回事。
以下是与创建和连接 websocket 相关的代码。
void
fail(beast::error_code ec, char const* what)
{
std::cerr << what << ": " << ec.message() << endl;
throw std::runtime_error("fail");
}
// Echoes back all received WebSocket messages
session::session(tcp::socket&& socket, queue<PQN_DATA_PACKET *> *pQ)
: ws_(std::move(socket))
{
cycle_cnt = 0;
phase_cnt = 0;
pconnectionQ = pQ;
m_portion = 0;
}
// Get on the correct executor
void session::run()
{
cout << "TODO session for " << endl;
// We need to be executing within a strand to perform async operations
// on the I/O objects in this session. Although not strictly necessary
// for single-threaded contexts, this example code is written to be
// thread-safe by default.
net::dispatch(ws_.get_executor(),
beast::bind_front_handler(
&session::on_run,
shared_from_this()));
}
// Start the asynchronous operation
void session::on_run()
{
cout << "ON_RUN_SESSION" << endl;
// Set suggested timeout settings for the websocket
ws_.set_option(
websocket::stream_base::timeout::suggested(
beast::role_type::server));
// Set a decorator to change the Server of the handshake
ws_.set_option(websocket::stream_base::decorator(
[](websocket::response_type& res)
{
res.set(http::field::server,
std::string(BOOST_BEAST_VERSION_STRING) +
" websocket-server-async");
}));
// Accept the websocket handshake
ws_.async_accept(
beast::bind_front_handler(
&session::on_accept,
shared_from_this()));
}
void session::on_accept(beast::error_code ec)
{
cout << "ON_ACCEPT SESSION" << endl;
if (ec)
return fail(ec, "accept");
// Read a message
// do_read();
// boost::this_thread::sleep_for(boost::chrono::milliseconds(1000));
// const int size = 256;
// unsigned char pu8rawbuf[size];
// for (int i = 0; i < size; i++) {
// pu8rawbuf[i] = rand() % 256;;
// }
cout << "accept connection" << endl;
//m_portion = 0;
//m_count_objects = 0;
//m_itr_doc = jsonDocumentData.MemberBegin();
//m_itr_arr = m_itr_doc->value.Begin();
//m_is_end_file = false;
do_write();
}
void session::do_read()
{
// Read a message into our buffer
ws_.async_read(
buffer_,
beast::bind_front_handler(
&session::on_read,
shared_from_this()));
}
void session::on_read(
beast::error_code ec,
std::size_t bytes_transferred)
{
boost::ignore_unused(bytes_transferred);
// This indicates that the session was closed
if (ec == websocket::error::closed)
return;
if (ec)
fail(ec, "read");
// Echo the message
ws_.text(ws_.got_text());
// auto jv = parse_file("./input2.json");
// pretty_print(std::cout, jv);
std::string stringForSending = std::string("TEST");
std::cout << "SENDED\n";
ws_.async_write(
net::buffer(stringForSending),
beast::bind_front_handler(
&session::on_write,
shared_from_this()));
}
错误发生在 session::on_accept() 函数中。错误信息如下:
TODO session for
ON_RUN_SESSION
DO_ACCEPT LISTENER
DO_ACCEPT LISTENER END
ON_ACCEPT SESSION
accept: The WebSocket handshake Connection field is missing the upgrade token
terminate called after throwing an instance of 'std::runtime_error'
what(): fail
我正在将 websocket 连接到本地托管的 node.js 服务器,端口号当然匹配。
以下代码片段来自 websocket 客户端。
const connectToWebSocketServer = () => {
const socket = new WebSocket(WEB_SOCKET_URL)
socket.onopen = (event) => {
console.warn('websocket connection established', event)
if (WEBSOCKET_CONNECTION_DURATION) {
setTimeout(() => {
socket.close()
console.warn('websocket connection closed')
}, WEBSOCKET_CONNECTION_DURATION)
}
}
谁能知道我的问题是什么以及我该如何解决这个问题?
提前致谢!
我再次完成了您的示例 - 这次是
#include <boost/asio.hpp>
#include <boost/beast.hpp>
#include <iostream>
#include <memory>
#include <queue>
namespace net = boost::asio;
namespace beast = boost::beast;
using net::ip::tcp;
using beast::error_code;
static void fail(error_code ec, std::string_view msg) {
std::cerr << msg << ": " << ec.message() << std::endl;
throw std::runtime_error("fail");
}
struct PQN_DATA_PACKET {
};
struct session : std::enable_shared_from_this<session> {
session(tcp::socket&& socket) : _socket(std::move(socket)) {}
void run()
{
std::cout << "TODO session for " << _socket.remote_endpoint()
<< std::endl;
}
private:
tcp::socket _socket;
};
using Queue = std::queue<PQN_DATA_PACKET*>;
struct listener : std::enable_shared_from_this<listener> {
net::io_context& _ioc;
tcp::acceptor _acceptor{_ioc};
Queue& _connectionQ;
listener(net::io_context& ioc, tcp::endpoint ep, Queue& connectionQ)
: _ioc(ioc)
, _acceptor(ioc, ep)
, _connectionQ(connectionQ)
{
}
// Start accepting incoming connections
void run() { do_accept(); }
void do_accept()
{
std::cout << "DO_ACCEPT LISTENER" << std::endl;
// The new connection gets its own strand
_acceptor.async_accept( //
net::make_strand(_ioc),
beast::bind_front_handler(&listener::on_accept,
shared_from_this()));
std::cout << "DO_ACCEPT LISTENER END" << std::endl;
}
void on_accept(beast::error_code ec, tcp::socket socket)
{
std::cout << "ON_ACCEPT LISTENER" << std::endl;
if (ec) {
fail(ec, "accept");
} else {
// Create the session and run it
std::make_shared<session>(std::move(socket) /*, _connectionQ*/)
->run();
}
// Accept another connection
do_accept();
}
};
struct server {
net::io_context _ioc;
Queue _connectionQ;
void run(tcp::endpoint ep, unsigned nthreads = 1) {
std::make_shared<listener>(_ioc, ep, _connectionQ) //
->run();
// Run the I/O service on the requested number of threads
std::vector<std::thread> v(nthreads);
for (auto& th : v)
th = std::thread([this] { _ioc.run(); });
for (auto& th : v)
if (th.joinable())
th.join();
}
};
int main() {
static uint16_t constexpr SERVER_PORT_NUMBER = 9797;
server srv;
srv.run({{}, SERVER_PORT_NUMBER}, 1);
}
然后我在节点中做了一个示例客户端:
#!/usr/bin/env node
var WebSocketClient = require('websocket').client;
var client = new WebSocketClient();
client.on('connectFailed', function(error) {
console.log('Connect Error: ' + error.toString());
});
client.on('connect', function(connection) {
console.log('WebSocket Client Connected');
connection.on('error', function(error) {
console.log("Connection Error: " + error.toString());
});
connection.on('close', function() {
console.log('echo-protocol Connection Closed');
});
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log("Received: '" + message.utf8Data + "'");
}
});
function sendNumber() {
if (connection.connected) {
var number = Math.round(Math.random() * 0xFFFFFF);
connection.sendUTF(number.toString());
console.log("Sending: '" + number.toString() + "'");
setTimeout(sendNumber, 1000);
}
}
sendNumber();
});
client.connect('ws://localhost:9797/', '');
我可以 运行 他们很好:
./sotest & npm install websocket && nodejs ./test.js
版画
[1] 14461
DO_ACCEPT LISTENER
DO_ACCEPT LISTENER END
added 18 packages, and audited 19 packages in 699ms
found 0 vulnerabilities
ON_ACCEPT LISTENER
TODO session for
DO_ACCEPT LISTENER
DO_ACCEPT LISTENER END
accept connection
WebSocket Client Connected
Sending: '7599795'
Received: '7599795'
Sending: '3553782'
Received: '3553782'
Sending: '13810406'
Received: '13810406'
Sending: '12580747'
Received: '12580747'
Sending: '3757113'
Received: '3757113'
等等