Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I am relatively new to C and C++ programming and I am trying to connect to a server using Websockets using the boost and beast libraries in C++. I followed the tutorial
here
but I get the following error
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
what(): The WebSocket handshake was declined by the remote peer [boost.beast.websocket:20]
This is my code so far. I need help figuring out the problem and also if you guys can include resources where I can become better at C++ and networking in general I would really appreciate it.
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <rapidjson/allocators.h>
#include <rapidjson/document.h>
#include <rapidjson/prettywriter.h>
#include <ta_libc.h>
#include <cstdlib>
#include <iostream>
#include <string>
using namespace std;
using namespace rapidjson;
namespace beast = boost::beast;
namespace http = beast::http;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = boost::asio::ip::tcp;
int main() {
string host = "ws-feed.exchange.coinbase.com";
auto const port = "443";
const char doc[] =
"{ \'type\': \'subscribe\', \'product_ids\': [\'ETH-USD\'], \'channels\': [\'matches\'] }";
Document document;
document.Parse(doc);
net::io_context ioc;
tcp::resolver resolver{ioc};
websocket::stream<tcp::socket> ws{ioc};
auto const results = resolver.resolve(host, port);
auto ep = net::connect(ws.next_layer(), results);
host += ":" + to_string(ep.port());
ws.set_option(websocket::stream_base::decorator(
[](websocket::request_type& req)
req.set(http::field::user_agent,
string(BOOST_BEAST_VERSION_STRING) +
" websocket-client-coro");
ws.handshake(host, "/");
ws.write(net::buffer(string(doc)));
beast::flat_buffer buffer;
ws.read(buffer);
ws.close(websocket::close_code::normal);
cout << beast::make_printable(buffer.data()) << endl;
} // main
–
–
–
Like others said, you don't use SSL where the server requires it.
Here's a demo. The subtler point is that the server required SNI.
#include <boost/beast.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/json.hpp>
#include <boost/json/src.hpp> // for header-only lib
#include <iostream>
namespace beast = boost::beast;
namespace http = beast::http;
namespace websocket = beast::websocket;
namespace net = boost::asio;
namespace ssl = net::ssl;
namespace json = boost::json;
using tcp = boost::asio::ip::tcp;
int main() {
std::string host = "ws-feed.exchange.coinbase.com";
auto const port = "443";
json::value doc = {
{"type", "subscribe"},
{"product_ids", {"ETH-USD"}},
{"channels", {"matches"}},
net::io_context ioc;
tcp::resolver resolver{ioc};
ssl::context ctx(ssl::context::sslv23_client);
ctx.set_default_verify_paths();
websocket::stream<ssl::stream<tcp::socket>> ws{ioc, ctx};
auto const results = resolver.resolve(host, port);
// connect raw socket
auto& raw = beast::get_lowest_layer(ws);
auto ep = net::connect(raw, results);
// Set SNI Hostname (many hosts need this to handshake successfully)
if (!SSL_set_tlsext_host_name(ws.next_layer().native_handle(), host.c_str())) {
throw boost::system::system_error(
::ERR_get_error(), boost::asio::error::get_ssl_category());
ws.next_layer().handshake(ssl::stream_base::client);
// ssl handshake
host += ":" + std::to_string(ep.port());
ws.set_option(
websocket::stream_base::decorator([](websocket::request_type& req) {
req.set(http::field::user_agent,
std::string(BOOST_BEAST_VERSION_STRING) +
" websocket-client-coro");
// websocket handshake
ws.handshake(host, "/");
std::cout << doc << std::endl;
ws.write(net::buffer(serialize(doc)));
beast::flat_buffer buffer;
ws.read(buffer);
std::cout << beast::make_printable(buffer.data()) << std::endl;
ws.close(websocket::close_code::normal);
Results in:
{"type":"subscribe","product_ids":["ETH-USD"],"channels":["matches"]}
{"type":"subscriptions","channels":[{"name":"matches","product_ids":["ETH-USD"]}]}
terminate called after throwing an instance of 'boost::wrapexcept<boost::system::system_error>'
what(): stream truncated [asio.ssl.stream:1]
The error indicates that the server doesn't gracefully shutdown the connection. That's probably by design.
–
–
–
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.