boost库websocket客户端
基于boost标准C++库,使用协程和beast实现websocket客户端。需要连接多少个websocket服务器协议地址,则创建多少个协程以及相应的处理函数即可。
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/spawn.hpp>
#include <cstdlib>
#include <functional>
#include <semaphore.h>
#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>
/* 报告错误信息
static void fail(beast::error_code ec, char const* what)
{
std::cerr << what << ": " << ec.message() << "\n";
}
*/
// prints the response
void do_session1(
std::string host,
std::string const& port,
std::string const& uri,
net::io_context& ioc,
net::yield_context yield)
{
beast::error_code ec;
while(1)
{
std::string strHost = host;
std::string strPort = port;
tcp::resolver resolver(ioc);
websocket::stream<beast::tcp_stream> ws(ioc);
beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
auto const results = resolver.async_resolve(strHost, strPort, yield[ec]);
auto ep = beast::get_lowest_layer(ws).async_connect(results, yield[ec]);
if (ec) {
fail(ec, "async_connect");
continue;
}
strHost += ':' + std::to_string(ep.port());
// Turn off the timeout on the tcp_stream, because
// the websocket stream has its own timeout system.
beast::get_lowest_layer(ws).expires_never();
// Set suggested timeout settings for the websocket
ws.set_option(websocket::stream_base::timeout::suggested(beast::role_type::client));
ws.async_handshake(strHost, uri, yield[ec]);
if (ec){
fail(ec, "async_handshake");
ws.close(websocket::close_code::normal);
continue;
}
while(1)
{
beast::flat_buffer buffer;
ws.async_read(buffer, yield[ec]);
if (ec) {
fail(ec, "async_read");
ws.close(websocket::close_code::normal);
break;
}
std::cout << std::string(beast::buffers_to_string(buffer.data()))) << std::endl;
buffer.clear();
}
}
}
void do_session2(
std::string host,
std::string const& port,
std::string const& uri,
net::io_context& ioc,
net::yield_context yield)
{
beast::error_code ec;
while(1)
{
std::string strHost = host;
std::string strPort = port;
tcp::resolver resolver(ioc);
websocket::stream<beast::tcp_stream> ws(ioc);
beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30));
auto const results = resolver.async_resolve(strHost, strPort, yield[ec]);
auto ep = beast::get_lowest_layer(ws).async_connect(results, yield[ec]);
if (ec) {
fail(ec, "async_connect");
continue;
}
strHost += ':' + std::to_string(ep.port());
// Turn off the timeout on the tcp_stream, because
// the websocket stream has its own timeout system.
beast::get_lowest_layer(ws).expires_never();
// Set suggested timeout settings for the websocket
ws.set_option(websocket::stream_base::timeout::suggested(beast::role_type::client));
ws.async_handshake(strHost, uri, yield[ec]);
if (ec){
fail(ec, "async_handshake");
ws.close(websocket::close_code::normal);
continue;
}
while(1)
{
beast::flat_buffer buffer;
// 需要添加ping及pong机制,这里暂不添加
ws.async_read(buffer, yield[ec]);
if (ec) {
fail(ec, "async_read");
ws.close(websocket::close_code::normal);
break;
}
std::cout << std::string(beast::buffers_to_string(buffer.data()))) << std::endl;
buffer.clear();
}
}
}
int main(void)
{
auto const host = "192.168.1.111";
auto const port = "9000";
try {
net::io_context ioc;
// 需要几个连接,创建对应个协程数量
boost::asio::spawn(ioc, std::bind(
&do_session1,
std::string(host),
std::string(port),
std::string("/aa/gagaga"),
std::ref(ioc),
std::placeholders::_1));
boost::asio::spawn(ioc, std::bind(
&do_session2,
std::string(host),
std::string(port),
std::string("/aa/lalala"),
std::ref(ioc),
std::placeholders::_1));
// Run the I/O service. The call will return when the socket is closed.
ioc.run();
} catch (std::exception const & e) {
std::cout << "error:" << e.what() << std::endl;
}
return NULL;
}
编译:
$:g++ -g -std=gnu++11 -o server websocket_client_coro.cpp -I/websocket/boost_1_73_0/ -L/websocket/boost_1_73_0/stage/lib -lboost_context -lboost_coroutine -lboost_chrono -lpthread