I posted a question earlier asking why does my server (written in C++ and boost::asio
) can't connect with a client (written in Javascript). Is the problem that the Javascript Websockets are different than boost::asio
sockets ? Does boost::asio
not support websockets ? What is the easiest way to work this out ?
Asked
Active
Viewed 6,778 times
8

Community
- 1
- 1

dimitris93
- 4,155
- 11
- 50
- 86
-
1Your best bet is probably [websocket++](https://github.com/zaphoyd/websocketpp). It has a `boost::asio` transport. As it is, you need to write your own websocket protocol code on top of `asio`, or use an existing library like websocket++. – Sean Cline Apr 11 '16 at 23:49
-
@SeanCline Can I not make javascript work with sockets instead ? – dimitris93 Apr 11 '16 at 23:51
-
@Shiro See [this question](http://stackoverflow.com/q/1736382/3962537) about that. – Dan Mašek Apr 11 '16 at 23:54
-
@DanMašek Let me ask a different question. Is it lame to use websockets instead of sockets to communicate with a c++ application on a server and an android application in java ? – dimitris93 Apr 11 '16 at 23:56
-
@Shiro I'm not familiar with the exact criteria to evaluate lameness, but depending on circumstances it might not be the best design decision. I'm not an android developer, but since you mention Java, a quick search nets [this](http://developer.android.com/reference/java/net/Socket.html). However, let's say you wanted to have support for both java apps, as well as some web-based application. In that case building your protocol on top of websockets might be a good choice. – Dan Mašek Apr 12 '16 at 00:02
-
1@DanMašek Yes, the problem is that I want to have support on android as well as browser. This is why I am thinking how will I make this work. – dimitris93 Apr 12 '16 at 00:03
-
@Shiro In that case, I'd probably choose websockets, just so that there's only one server implementation to deal with. On Android, I'd probably look for some [Java implementation of websockets](https://github.com/TooTallNate/Java-WebSocket), so you don't need to do the communications in JS. – Dan Mašek Apr 12 '16 at 00:09
-
1@DanMašek For the record, `Wesocketpp` worked perfectly. Thank you. It is by far the easiest way to use websockets in C++. First install `boost` and then add `Websocketpp` as a header-only library to a project. – dimitris93 Apr 13 '16 at 12:02
1 Answers
10
Boost.Beast, now part of Boost, is built on top of Boost.Asio and works the way you expect. It comes with example code and documentation. Check it out here: www.boost.org/libs/beast
Here's a complete program that sends a message to the echo server:
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
// Sends a WebSocket message and prints the response
int main(int argc, char** argv)
{
try
{
// Check command line arguments.
if(argc != 4)
{
std::cerr <<
"Usage: websocket-client-sync <host> <port> <text>\n" <<
"Example:\n" <<
" websocket-client-sync echo.websocket.org 80 \"Hello, world!\"\n";
return EXIT_FAILURE;
}
std::string host = argv[1];
auto const port = argv[2];
auto const text = argv[3];
// The io_context is required for all I/O
net::io_context ioc;
// These objects perform our I/O
tcp::resolver resolver{ioc};
websocket::stream<tcp::socket> ws{ioc};
// Look up the domain name
auto const results = resolver.resolve(host, port);
// Make the connection on the IP address we get from a lookup
auto ep = net::connect(ws.next_layer(), results);
// Update the host_ string. This will provide the value of the
// Host HTTP header during the WebSocket handshake.
// See https://tools.ietf.org/html/rfc7230#section-5.4
host += ':' + std::to_string(ep.port());
// Set a decorator to change the User-Agent of the handshake
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");
}));
// Perform the websocket handshake
ws.handshake(host, "/");
// Send the message
ws.write(net::buffer(std::string(text)));
// This buffer will hold the incoming message
beast::flat_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 make_printable() function helps print a ConstBufferSequence
std::cout << beast::make_printable(buffer.data()) << std::endl;
}
catch(std::exception const& e)
{
std::cerr << "Error: " << e.what() << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}

Vinnie Falco
- 5,173
- 28
- 43
-
Really appreciate your responses RE websockets. Would it be possible to update this answer given that your library is now part of Boost? There were some namespaces/classes I could not find. – user997112 Jun 22 '22 at 22:40
-
May I ask what is this line required for: `req.set(http::field::user_agent, std::string(BOOST_BEAST_VERSION_STRING) + " websocket-client-coro");` ? – user997112 Jun 24 '22 at 05:14
-
Does it not compile? It compiles and passes tests for me, on CI. Please open an issue. – Vinnie Falco Jun 25 '22 at 03:03
-
Sorry i wasn't implying there was a problem, I just wondered why it is needed? – user997112 Jun 25 '22 at 03:58
-