C++ – 使用Websocket++编写客户端连接WebSocket服务器并进行通信
1 库依赖
使用Websocket++有两种方案:
- Websocket++ + boost,主要是使用Boost Asio,这种方案比较重依赖,需要链接Boost
- Websocket++ + 独立Asio库,这种方案比较轻量,Websocket++和独立Asio都只需要使用头文件即可,具体的配置方案可参考我这篇文章:C++ – websocket++不依赖boost,基于独立Asio编译方法
推荐使用第二种方案,比较轻量,跨平台编译也比较方便。
2 根据官方示例代码修改封装的WebsocketClient类
2.1 WebsocketClient代码
- WebsocketClient.h
#ifndef WEBSOCKET_CLIENT_H
#define WEBSOCKET_CLIENT_H
// 不包含TLS Client
#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
// 包含TLS Client
// #include <websocketpp/config/asio_client.hpp>
// #include <websocketpp/client.hpp>
#include <websocketpp/common/thread.hpp>
#include <websocketpp/common/memory.hpp>
#include <string>
#include <locale>
#include <codecvt>
typedef websocketpp::client<websocketpp::config::asio_client> client;
static std::wstring string_to_wstring(const std::string &s)
{
using default_convert = std::codecvt<wchar_t, char, std::mbstate_t>;
static std::wstring_convert<default_convert>conv(new default_convert("CHS"));
return conv.from_bytes(s);
}
static std::string wstring_to_string(const std::wstring &s)
{
using default_convert = std::codecvt<wchar_t, char, std::mbstate_t>;
static std::wstring_convert<default_convert>conv(new default_convert("CHS"));
return conv.to_bytes(s);
}
static std::string ansi_to_utf8(const std::string &s)
{
static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
return conv.to_bytes(string_to_wstring(s));
}
static std::string utf8_to_ansi(const std::string& s)
{
static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
return wstring_to_string(conv.from_bytes(s));
}
// 保存一个连接的metadata
class connection_metadata {
public:
typedef websocketpp::lib::shared_ptr<connection_metadata> ptr;
connection_metadata(websocketpp::connection_hdl hdl, std::string url)
: m_Hdl(hdl)
, m_Status("Connecting")
, m_Url(url)
, m_Server("N/A")
{}
void on_open(client * c, websocketpp::connection_hdl hdl)
{
m_Status = "Open";
client::connection_ptr con = c->get_con_from_hdl(hdl);
m_Server = con->get_response_header("Server");
}
void on_fail(client * c, websocketpp::connection_hdl hdl)
{
m_Status = "Failed";
client::connection_ptr con = c->get_con_from_hdl(hdl);
m_Server = con->get_response_header("Server");
m_Error_reason = con->get_ec().message();
}
void on_close(client * c, websocketpp::connection_hdl hdl)
{
m_Status = "Closed";
client::connection_ptr con = c->get_con_from_hdl(hdl);
std::stringstream s;
s << "close code: " << con->get_remote_close_code() << " ("
<< websocketpp::close::status::get_string(con->get_remote_close_code())
<< "), close reason: " << con->get_remote_close_reason();
m_Error_reason = s.str();
}
void on_message(websocketpp::connection_hdl, client::message_ptr msg)
{
if (msg->get_opcode() == websocketpp::frame::opcode::text)
{
std::string message = utf8_to_ansi(msg->get_payload());
std::cout << "收到来自服务器的消息:" << message << std::endl;
}
else
{
std::string message = websocketpp::utility::to_hex(msg->get_payload());
}
}
websocketpp::connection_hdl get_hdl() const
{
return m_Hdl;
}
std::string get_status() const
{
return m_Status;
}
private:
websocketpp::connection_hdl m_Hdl; // websocketpp表示连接的编号
std::string m_Status; // 连接自动状态
std::string m_Url; // 连接的URI
std::string m_Server; // 服务器信息
std::string m_Error_reason; // 错误原因
};
class WebsocketClient
{
public:
WebsocketClient();
virtual~WebsocketClient();
public:
bool Connect(std::string const & url);
bool Close(std::string reason = "");
bool Send(std::string message);
connection_metadata::ptr GetConnectionMetadataPtr();
private:
connection_metadata::ptr m_ConnectionMetadataPtr;
client m_WebsocketClient;
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_Thread; // 线程
};
#endif // !WEBSOCKET_ENDPOINT_H
- WebsocketClient.cpp
#include "WebsocketClient.h"
WebsocketClient::WebsocketClient()
{
m_WebsocketClient.clear_access_channels(websocketpp::log::alevel::all); // 开启全部接入日志级别
m_WebsocketClient.clear_error_channels(websocketpp::log::elevel::all); // 开启全部错误日志级别
m_WebsocketClient.init_asio(); // 初始化asio
m_WebsocketClient.start_perpetual(); // 避免请求为空时退出,实际上,也是避免asio退出
// 独立运行client::run()的线程,主要是避免阻塞
m_Thread = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &m_WebsocketClient);
}
WebsocketClient::~WebsocketClient()
{
m_WebsocketClient.stop_perpetual();
if (m_ConnectionMetadataPtr != nullptr && m_ConnectionMetadataPtr->get_status() == "Open")
{
websocketpp::lib::error_code ec;
m_WebsocketClient.close(m_ConnectionMetadataPtr->get_hdl(), websocketpp::close::status::going_away, "", ec); // 关闭连接
if (ec) {
std::cout << "> Error initiating close: " << ec.message() << std::endl;
}
}
m_Thread->join();
}
bool WebsocketClient::Connect(std::string const & url)
{
websocketpp::lib::error_code ec;
// 创建connect的共享指针,注意,此时创建并没有实际建立
client::connection_ptr con = m_WebsocketClient.get_connection(url, ec);
if (ec) {
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
return false;
}
// 创建连接的metadata信息,并保存
connection_metadata::ptr metadata_ptr = websocketpp::lib::make_shared<connection_metadata>(con->get_handle(), url);
m_ConnectionMetadataPtr = metadata_ptr;
// 注册连接打开的Handler
con->set_open_handler(websocketpp::lib::bind(
&connection_metadata::on_open,
metadata_ptr,
&m_WebsocketClient,
websocketpp::lib::placeholders::_1
));
// 注册连接失败的Handler
con->set_fail_handler(websocketpp::lib::bind(
&connection_metadata::on_fail,
metadata_ptr,
&m_WebsocketClient,
websocketpp::lib::placeholders::_1
));
// 注册连接关闭的Handler
con->set_close_handler(websocketpp::lib::bind(
&connection_metadata::on_close,
metadata_ptr,
&m_WebsocketClient,
websocketpp::lib::placeholders::_1
));
// 注册连接接收消息的Handler
con->set_message_handler(websocketpp::lib::bind(
&connection_metadata::on_message,
metadata_ptr,
websocketpp::lib::placeholders::_1,
websocketpp::lib::placeholders::_2
));
// 进行连接
m_WebsocketClient.connect(con);
std::cout << "Websocket连接成功" << std::endl;
return true;
}
bool WebsocketClient::Close(std::string reason)
{
websocketpp::lib::error_code ec;
if (m_ConnectionMetadataPtr != nullptr)
{
int close_code = websocketpp::close::status::normal;
// 关闭连接
m_WebsocketClient.close(m_ConnectionMetadataPtr->get_hdl(), close_code, reason, ec);
if (ec) {
std::cout << "> Error initiating close: " << ec.message() << std::endl;
return false;
}
std::cout << "关闭Websocket连接成功" << std::endl;
}
return true;
}
bool WebsocketClient::Send(std::string message)
{
websocketpp::lib::error_code ec;
if (m_ConnectionMetadataPtr != nullptr)
{
// 连接发送数据
m_WebsocketClient.send(m_ConnectionMetadataPtr->get_hdl(), ansi_to_utf8(message), websocketpp::frame::opcode::text, ec);
if (ec) {
std::cout << "> Error sending message: " << ec.message() << std::endl;
return false;
}
std::cout << "发送数据成功" << std::endl;
}
return true;
}
connection_metadata::ptr WebsocketClient::GetConnectionMetadataPtr()
{
return m_ConnectionMetadataPtr;
}
2.2 WebsocketClient类使用代码
#include "WebsocketClient.h"
int main() {
bool done = false;
std::string input;
WebsocketClient endpoint;
while (!done) {
std::cout << "Enter Command: ";
std::getline(std::cin, input);
if (input == "quit") {
done = true;
}
else if (input == "help") {
std::cout
<< "\nCommand List:\n"
<< "connect <ws uri>\n"
<< "send <message>\n"
<< "close [<close code:default=1000>] [<close reason>]\n"
<< "help: Display this help text\n"
<< "quit: Exit the program\n"
<< std::endl;
}
else if (input.substr(0, 7) == "connect") {
endpoint.Connect(input.substr(8));
}
else if (input.substr(0, 4) == "send") {
std::stringstream ss(input);
std::string cmd;
int id;
std::string message;
ss >> cmd;
std::getline(ss, message);
endpoint.Send(message);
}
else if (input.substr(0, 5) == "close") {
std::stringstream ss(input);
std::string cmd;
std::string reason;
ss >> cmd ;
std::getline(ss, reason);
endpoint.Close(reason);
}
else if (input.substr(0, 4) == "quit") {
done = true;
}
else {
std::cout << "> Unrecognized Command" << std::endl;
}
}
return 0;
}
3 Websocket++官方编写客户端示例教程
可参考链接:https://docs.websocketpp.org/md_tutorials_utility_client_utility_client.html
也可在Websocket++的文件夹\tutorials\utility_client找到该示例!
或者在Websocket++的文件夹\example\scratch_client找到该示例!
4 与Websocket++官方示例客户端的不同
- 增加ansi与utf-8编码转换,中文字符不再乱码
- 不适用官方使用id管理多个链接方式,这里认为的客户端只有一个长连接,而WebsocketClient只维护一个长连接即可
2020年9月16日更新:修改WebsocketClient类
修改信息
- 将open,close,message等回调函数移动到WebsocketClient内部
- 新增设置回调函数的公共接口
WebsocketClient.h
#ifndef WEBSOCKET_CLIENT_H
#define WEBSOCKET_CLIENT_H
// 不包含TLS Client
#include <websocketpp/config/asio_no_tls_client.hpp>
#include <websocketpp/client.hpp>
// 包含TLS Client
// #include <websocketpp/config/asio_client.hpp>
// #include <websocketpp/client.hpp>
#include <websocketpp/common/thread.hpp>
#include <websocketpp/common/memory.hpp>
#include <string>
#include <locale>
#include <codecvt>
typedef websocketpp::client<websocketpp::config::asio_client> client;
static std::wstring string_to_wstring(const std::string &s)
{
using default_convert = std::codecvt<wchar_t, char, std::mbstate_t>;
static std::wstring_convert<default_convert>conv(new default_convert("CHS"));
return conv.from_bytes(s);
}
static std::string wstring_to_string(const std::wstring &s)
{
using default_convert = std::codecvt<wchar_t, char, std::mbstate_t>;
static std::wstring_convert<default_convert>conv(new default_convert("CHS"));
return conv.to_bytes(s);
}
static std::string ansi_to_utf8(const std::string &s)
{
static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
return conv.to_bytes(string_to_wstring(s));
}
static std::string utf8_to_ansi(const std::string& s)
{
static std::wstring_convert<std::codecvt_utf8<wchar_t> > conv;
return wstring_to_string(conv.from_bytes(s));
}
typedef std::function<void()> OnOpenFunc;
typedef std::function<void()> OnFailFunc;
typedef std::function<void()> OnCloseFunc;
typedef std::function<void(const std::string& message)> OnMessageFunc;
class WebsocketClient
{
public:
WebsocketClient();
virtual~WebsocketClient();
public:
bool Connect(std::string const & url);
bool Close(std::string reason = "");
bool Send(std::string message);
connection_metadata::ptr GetConnectionMetadataPtr();
void OnOpen(client * c, websocketpp::connection_hdl hdl);
void OnFail(client * c, websocketpp::connection_hdl hdl);
void OnClose(client * c, websocketpp::connection_hdl hdl);
void OnMessage(websocketpp::connection_hdl, client::message_ptr msg);
void SetOnOpenFunc(OnOpenFunc func);
void SetOnFailFunc(OnFailFunc func);
void SetOnCloseFunc(OnCloseFunc func);
void SetMessageFunc(OnMessageFunc func);
private:
connection_metadata::ptr m_ConnectionMetadataPtr;
client m_WebsocketClient;
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_Thread; // 线程
OnOpenFunc m_OnOpenFunc;
OnFailFunc m_OnFailFunc;
OnCloseFunc m_OnCloseFunc;
OnMessageFunc m_MessageFunc;
};
#endif // !WEBSOCKET_ENDPOINT_H
WebsocketClient.cpp
#include "WebsocketClient.h"
WebsocketClient::WebsocketClient()
{
m_WebsocketClient.clear_access_channels(websocketpp::log::alevel::all); // 开启全部接入日志级别
m_WebsocketClient.clear_error_channels(websocketpp::log::elevel::all); // 开启全部错误日志级别
m_WebsocketClient.init_asio(); // 初始化asio
m_WebsocketClient.start_perpetual(); // 避免请求为空时退出,实际上,也是避免asio退出
// 独立运行client::run()的线程,主要是避免阻塞
m_Thread = websocketpp::lib::make_shared<websocketpp::lib::thread>(&client::run, &m_WebsocketClient);
m_OnOpenFunc = nullptr;
m_OnFailFunc = nullptr;
m_OnCloseFunc = nullptr;
m_MessageFunc = nullptr;
}
WebsocketClient::~WebsocketClient()
{
m_WebsocketClient.stop_perpetual();
if (m_ConnectionMetadataPtr != nullptr && m_ConnectionMetadataPtr->get_status() == "Open")
{
websocketpp::lib::error_code ec;
m_WebsocketClient.close(m_ConnectionMetadataPtr->get_hdl(), websocketpp::close::status::going_away, "", ec); // 关闭连接
if (ec) {
std::cout << "> Error initiating close: " << ec.message() << std::endl;
}
}
m_Thread->join();
}
bool WebsocketClient::Connect(std::string const & url)
{
websocketpp::lib::error_code ec;
// 创建connect的共享指针,注意,此时创建并没有实际建立
client::connection_ptr con = m_WebsocketClient.get_connection(url, ec);
if (ec) {
std::cout << "> Connect initialization error: " << ec.message() << std::endl;
return false;
}
// 创建连接的metadata信息,并保存
connection_metadata::ptr metadata_ptr = websocketpp::lib::make_shared<connection_metadata>(con->get_handle(), url);
m_ConnectionMetadataPtr = metadata_ptr;
// 注册连接打开的Handler
//con->set_open_handler(websocketpp::lib::bind(
// &connection_metadata::on_open,
// metadata_ptr,
// &m_WebsocketClient,
// websocketpp::lib::placeholders::_1
//));
con->set_open_handler(websocketpp::lib::bind(
&WebsocketClient::OnOpen,
this,
&m_WebsocketClient,
websocketpp::lib::placeholders::_1
));
// 注册连接失败的Handler
//con->set_fail_handler(websocketpp::lib::bind(
// &connection_metadata::on_fail,
// metadata_ptr,
// &m_WebsocketClient,
// websocketpp::lib::placeholders::_1
//));
con->set_fail_handler(websocketpp::lib::bind(
&WebsocketClient::OnFail,
this,
&m_WebsocketClient,
websocketpp::lib::placeholders::_1
));
// 注册连接关闭的Handler
//con->set_close_handler(websocketpp::lib::bind(
// &connection_metadata::on_close,
// metadata_ptr,
// &m_WebsocketClient,
// websocketpp::lib::placeholders::_1
//));
con->set_close_handler(websocketpp::lib::bind(
&WebsocketClient::OnClose,
this,
&m_WebsocketClient,
websocketpp::lib::placeholders::_1
));
// 注册连接接收消息的Handler
//con->set_message_handler(websocketpp::lib::bind(
// &connection_metadata::on_message,
// metadata_ptr,
// websocketpp::lib::placeholders::_1,
// websocketpp::lib::placeholders::_2
//));
con->set_message_handler(websocketpp::lib::bind(
&WebsocketClient::OnMessage,
this,
websocketpp::lib::placeholders::_1,
websocketpp::lib::placeholders::_2
));
// 进行连接
m_WebsocketClient.connect(con);
std::cout << "Websocket连接成功" << std::endl;
// 注意,不能在Websocket连接完成之后马上就发送消息,不然会出现Invalid State的错误,
// 导致消息发送不成功,所以在连接成功之后,主线程休眠1秒
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
return true;
}
bool WebsocketClient::Close(std::string reason)
{
websocketpp::lib::error_code ec;
if (m_ConnectionMetadataPtr != nullptr)
{
int close_code = websocketpp::close::status::normal;
// 关闭连接
m_WebsocketClient.close(m_ConnectionMetadataPtr->get_hdl(), close_code, reason, ec);
if (ec) {
std::cout << "> Error initiating close: " << ec.message() << std::endl;
return false;
}
std::cout << "关闭Websocket连接成功" << std::endl;
}
return true;
}
bool WebsocketClient::Send(std::string message)
{
websocketpp::lib::error_code ec;
if (m_ConnectionMetadataPtr != nullptr)
{
// 连接发送数据
m_WebsocketClient.send(m_ConnectionMetadataPtr->get_hdl(),ansi_to_utf8(message), websocketpp::frame::opcode::text, ec);
if (ec)
{
std::cout << "> Error sending message: " << ec.message() << std::endl;
std::string errorMessage = ec.message();
return false;
}
std::cout << "发送数据成功" << std::endl;
}
return true;
}
connection_metadata::ptr WebsocketClient::GetConnectionMetadataPtr()
{
return m_ConnectionMetadataPtr;
}
void WebsocketClient::OnOpen(client * c, websocketpp::connection_hdl hdl)
{
if (m_OnOpenFunc != nullptr)
{
m_OnOpenFunc();
}
}
void WebsocketClient::OnFail(client * c, websocketpp::connection_hdl hdl)
{
if (m_OnFailFunc != nullptr)
{
m_OnFailFunc();
}
}
void WebsocketClient::OnClose(client * c, websocketpp::connection_hdl hdl)
{
if (m_OnCloseFunc != nullptr)
{
m_OnCloseFunc();
}
}
void WebsocketClient::OnMessage(websocketpp::connection_hdl, client::message_ptr msg)
{
if (msg->get_opcode() == websocketpp::frame::opcode::text)
{
std::string message = utf8_to_ansi(msg->get_payload());
//std::cout << "收到来自服务器的消息:" << message << std::endl;
if (m_MessageFunc != nullptr)
{
m_MessageFunc(message);
}
}
else
{
std::string message = websocketpp::utility::to_hex(msg->get_payload());
}
}
void WebsocketClient::SetOnOpenFunc(OnOpenFunc func)
{
m_OnOpenFunc = func;
}
void WebsocketClient::SetOnFailFunc(OnFailFunc func)
{
m_OnFailFunc = func;
}
void WebsocketClient::SetOnCloseFunc(OnCloseFunc func)
{
m_OnCloseFunc = func;
}
void WebsocketClient::SetMessageFunc(OnMessageFunc func)
{
m_MessageFunc = func;
}
另外在应用该类的时候发现了一个Websocket++的一个问题: 不能在Websocket连接完成之后马上就发送消息,不然会出现Invalid State的错误,导致消息发送不成功,所以在连接成功之后,主线程休眠1秒,这在代码中也有体现。
5 进一步升级的WebsocketClient类
更新于2023年9月7日,新版本WebsocketClient类代码变更如下:
- 更加简单,开箱即用
- 新增发送二进制数据到服务器的功能函数
websocket_client.h
#ifndef _WEBSOCKET_CLIENT_H_
#define _WEBSOCKET_CLIENT_H_
#include "websocketpp/config/asio_no_tls_client.hpp"
#include "websocketpp/client.hpp"
#include <string>
typedef websocketpp::client<websocketpp::config::asio_client> client;
class WebsocketClient
{
public:
WebsocketClient();
virtual~ WebsocketClient();
public:
bool Connect(const std::string& ws_url);
bool Close(const std::string& close_reason= "");
bool SendTextToServer(const std::string& message);
bool SendBinaryToServer(void* data, int data_length);
void SendTextToServerUntilSuccess(const std::string& message);
void SendBinaryToServerUntilSuccess(void* data, int data_length);
bool Ping();
private:
void OnSocketInit(websocketpp::connection_hdl hdl);
void OnOpen(websocketpp::connection_hdl hdl);
void OnMessage(websocketpp::connection_hdl hdl, client::message_ptr msg);
void OnFail(websocketpp::connection_hdl hdl);
void OnClose(websocketpp::connection_hdl hdl);
private:
client m_end_point;
websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread_ptr;
client::connection_ptr m_connection_ptr;
};
#endif // !_WEBSOCKET_CLIENT_H_
websocket_client.cpp
#include "websocket_client.h"
static std::string utf8_to_gbk(const std::string& utf8_str)
{
int len = MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, NULL, 0);
wchar_t* wszGBK = new wchar_t[len + 1];
memset(wszGBK, 0, len * 2 + 2);
MultiByteToWideChar(CP_UTF8, 0, utf8_str.c_str(), -1, wszGBK, len);
len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
char* szGBK = new char[len + 1];
memset(szGBK, 0, len + 1);
WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
std::string strTemp(szGBK);
if (wszGBK) delete[] wszGBK;
if (szGBK) delete[] szGBK;
return strTemp;
}
WebsocketClient::WebsocketClient()
:m_thread_ptr(nullptr),
m_connection_ptr(nullptr)
{
m_end_point.clear_access_channels(websocketpp::log::alevel::all);
m_end_point.clear_error_channels(websocketpp::log::elevel::all);
m_end_point.init_asio();
m_end_point.start_perpetual();
m_thread_ptr.reset(new websocketpp::lib::thread(&client::run, &m_end_point));
}
WebsocketClient::~WebsocketClient()
{
m_end_point.stop_perpetual();
if (m_connection_ptr->get_state() == websocketpp::session::state::open ||
m_connection_ptr->get_state() == websocketpp::session::state::connecting )
{
websocketpp::lib::error_code ec;
m_end_point.close(m_connection_ptr->get_handle(), websocketpp::close::status::going_away, "", ec);
if (ec)
{
std::cout << "websocket close is failed, the error message is : " << ec.message() << std::endl;
}
}
m_thread_ptr->join();
m_thread_ptr.reset();
m_thread_ptr = nullptr;
}
bool WebsocketClient::Connect(const std::string& ws_url)
{
websocketpp::lib::error_code ec;
client::connection_ptr con = m_end_point.get_connection(ws_url, ec);
if (ec) {
std::cout << "connect to websocket server is failed, the error message is : " << ec.message() << std::endl;
return false;
}
m_connection_ptr = con;
// 设置各种消息的回调函数
con->set_socket_init_handler(websocketpp::lib::bind(&WebsocketClient::OnSocketInit, this, websocketpp::lib::placeholders::_1));
con->set_open_handler(websocketpp::lib::bind(&WebsocketClient::OnOpen, this, websocketpp::lib::placeholders::_1));
con->set_fail_handler(websocketpp::lib::bind(&WebsocketClient::OnFail, this, websocketpp::lib::placeholders::_1));
con->set_close_handler(websocketpp::lib::bind(&WebsocketClient::OnClose, this, websocketpp::lib::placeholders::_1));
con->set_message_handler(websocketpp::lib::bind(&WebsocketClient::OnMessage, this, websocketpp::lib::placeholders::_1, websocketpp::lib::placeholders::_2));
// 连接服务器
m_end_point.connect(con);
return true;
}
bool WebsocketClient::Close(const std::string& close_reason)
{
if (m_connection_ptr == nullptr)
{
std::cout << "the websocket connection is nullptr" << std::endl;
return false;
}
websocketpp::lib::error_code ec;
m_end_point.close(m_connection_ptr->get_handle(), websocketpp::close::status::normal, close_reason, ec);
if (ec)
{
std::cout << "websocket close is failed, the error message is : " << ec.message() << std::endl;
return false;
}
return true;
}
bool WebsocketClient::SendTextToServer(const std::string& message)
{
if (m_connection_ptr == nullptr)
{
std::cout << "websocket client send message failed, the connection is nullptr !" << std::endl;
return false;
}
if (m_connection_ptr->get_state() == websocketpp::session::state::open)
{
websocketpp::lib::error_code ec;
m_end_point.send(m_connection_ptr->get_handle(), message, websocketpp::frame::opcode::text, ec);
if (ec)
{
std::cout << "websocket client send message failed, the error message is : " << ec.message() << std::endl;
return false;
}
}
else
{
std::cout << "websocket client send message failed, the websocket is not open" << std::endl;
return false;
}
return true;
}
bool WebsocketClient::SendBinaryToServer(void* data, int data_length)
{
if (m_connection_ptr == nullptr)
{
std::cout << "websocket client send message failed, the connection is nullptr !" << std::endl;
return false;
}
if (m_connection_ptr->get_state() == websocketpp::session::state::open)
{
websocketpp::lib::error_code ec;
m_end_point.send(m_connection_ptr->get_handle(), data, data_length, websocketpp::frame::opcode::binary, ec);
if (ec)
{
std::cout << "websocket client send message failed, the error message is : " << ec.message() << std::endl;
return false;
}
}
else
{
std::cout << "websocket client send message failed, the websocket is not open" << std::endl;
return false;
}
return true;
}
void WebsocketClient::SendTextToServerUntilSuccess(const std::string& message)
{
bool send_state = false;
do
{
send_state = SendTextToServer(message);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
} while (!send_state);
}
void WebsocketClient::SendBinaryToServerUntilSuccess(void* data, int data_length)
{
bool send_state = false;
do
{
send_state = SendBinaryToServer(data, data_length);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
} while (!send_state);
}
bool WebsocketClient::Ping()
{
if (m_connection_ptr != nullptr)
{
websocketpp::lib::error_code ec;
m_end_point.ping(m_connection_ptr->get_handle(), "ping", ec);
if (ec)
{
std::cout << "websocket client ping failed, the error message is : " << ec.message() << std::endl;
return false;
}
}
return true;
}
void WebsocketClient::OnSocketInit(websocketpp::connection_hdl hdl)
{
}
void WebsocketClient::OnOpen(websocketpp::connection_hdl hdl)
{
std::cout << "websocket连接open" << std::endl;
}
void WebsocketClient::OnMessage(websocketpp::connection_hdl hdl, client::message_ptr msg)
{
std::cout << "服务器发送信息:"<<utf8_to_gbk(msg->get_payload()) << std::endl;
}
void WebsocketClient::OnFail(websocketpp::connection_hdl hdl)
{
client::connection_ptr con = m_end_point.get_con_from_hdl(hdl);
int fail_local_close_code = con->get_local_close_code();
std::string fail_local_close_reson = con->get_local_close_reason();
int fail_remote_close_code = con->get_remote_close_code();
std::string fail_remote_close_reason = con->get_remote_close_reason();
std::string fail_message = con->get_ec().message();
int fail_code = con->get_ec().value();
std::cout << "failed code : " << fail_remote_close_code << " failed message : " << fail_message << std::endl;
}
void WebsocketClient::OnClose(websocketpp::connection_hdl hdl)
{
client::connection_ptr con = m_end_point.get_con_from_hdl(hdl);
int close_code = con->get_remote_close_code();
std::string close_reason = con->get_remote_close_reason();
std::cout << "close code : " << close_code << " close message : " << close_reason << std::endl;
}
本文作者:StubbornHuang
版权声明:本文为站长原创文章,如果转载请注明原文链接!
原文标题:C++ – 使用Websocket++编写客户端连接WebSocket服务器并进行通信
原文链接:https://www.stubbornhuang.com/905/
发布于:2020年08月31日 17:39:12
修改于:2023年09月07日 10:55:57
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论
51