1、背景介绍
1.1 WebSocket介绍
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
1.2 WebSocket 属性
连接状态属性
以下是 WebSocket 对象的属性:
0 - 表示连接尚未建立。
1 - 表示连接已建立,可以进行通信。
2 - 表示连接正在进行关闭。
3 - 表示连接已经关闭或者连接不能打开。
Socket.bufferedAmount
只读属性 bufferedAmount 为True表示信息已被 send() 放入正在队列中等待传输,但是还没有发出的 UTF-8 文本字节数。
WebSocket 事件
以下是 WebSocket 对象的相关事件:
事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发
WebSocket 方法
以下是 WebSocket 对象的相关方法,用于信息发生与连接
方法 描述
Socket.send() //使用连接发送数据
Socket.close() //关闭连接
1.3 easywsclient介绍
websocket并不局限于在网页端(JS客户端使用),其还支持在各个后端中使用,如C++、Java等
easywsclient是一个基于C++11的轻量化标注websocket客户端库(跨平台,支持各种系统),支持RFC 6455版本13 WebSocket,兼容现行所有的WebSocket服务器(如c++ crow库的WebSocket服务端)。对于socketio的服务器兼容存在问题,应使用socketio的客户端。
项目地址: https://github.com/dhbaird/easywsclient
2、easywsclient使用
2.1 代码介绍
easywsclient项目核心代码为"easywsclient.hpp"和"easywsclient.cpp",仅需将这两个文件拷贝到自己项目下即可使用WebSocket客户端通信了。
其关键接口函数有以下4个,send函数用于发送文本信息,sendBinary函数用于发送二进制信息,dispatch用于设置信息接收处理的函数
ws->poll();
ws->send("hello");
//ws->sendBinary(vp);
ws->dispatch(handle_message);
2.2 基本使用
使用easywsclient主要是要指定dispatch函数,可以在dispatch函数中对服务器返回的信息进行处理,也可以在此处断开WebSocket连接
#include "easywsclient.hpp"
//#include "easywsclient.cpp" // <-- include only if you don't want compile separately
using easywsclient::WebSocket;
WebSocket::pointer ws;
void handle_message_close(const std::string& message)
{
ws->close();
}
int
main()
{
#ifdef _WIN32
INT rc;
WSADATA wsaData;
rc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (rc) {
printf("WSAStartup Failed.\n");
return 1;
}
#endif
ws = WebSocket::from_url("ws://localhost:8126/foo");
assert(ws);
while (websocketclient->getReadyState() != WebSocket::CLOSED) {
ws->poll();
ws->send("hello");
ws->dispatch(handle_message_close);
}
...
delete ws; // alternatively, use unique_ptr<> if you have C++11
#ifdef _WIN32
WSACleanup();
#endif
return 0;
}
2.3 发送二进制数据
需要调用sendBinary函数,其入参为std::vector<uint8_t>类型。其支持将多种数据类型进行拼接,允许一次性传入多个数据(使用memcpy将数据复制到对应内存位置即可)。
long dsize = sizeof(int) +sizeof(char) * txt_data.size() ;
uint8_t* buffer;
buffer = (uint8_t*)malloc(sizeof(uint8_t) * dsize);
memcpy(buffer, 123456, sizeof(int));
memcpy(buffer+sizeof(int), txt_data.data(), sizeof(char)*txt_data.size());
std::vector<uint8_t> vp(buffer, buffer + dsize);
ws->poll();
ws->sendBinary(vp);
//可以将二进制数据保存下来,与服务器端进行验证
ofstream fout("send.dat", ios::binary);
fout.write(reinterpret_cast<const char*>(buffer), sizeof(uint8_t) * dsize);
fout.close();
3、websocket服务器
在c++下搭建websocket服务器需要依赖其他的第三方库,这里初略介绍一下2个可以实现websocket服务器的c++库
3.1 使用websocketpp库
websocketpp库下载地址为:https://github.com/zaphoyd/websocketpp/,其依赖Boost库。故此,在导入websocketpp库前,需要先导入Boost库。websocketpp库也支持websocket客户端,但考虑到依赖的库更多了,还是推荐使用easywsclient库
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
// pull out the type of messages sent by our config
typedef server::message_ptr message_ptr;
// Define a callback to handle incoming messages
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) {
std::string cmd = msg->get_payload();
std::string res = "fu wu qi de xin xi! \" ";
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " and message: " << msg->get_payload()
<< std::endl;
// check for a special command to instruct the server to stop listening so
// it can be cleanly exited.
if (msg->get_payload() == "stop-listening") {
s->stop_listening();
return;
}
try {
s->send(hdl, res, msg->get_opcode());
} catch (websocketpp::exception const & e) {
std::cout << "Echo failed because: "
<< "(" << e.what() << ")" << std::endl;
}
}
int main() {
// Create a server endpoint
server echo_server;
try {
// Set logging settings
echo_server.set_access_channels(websocketpp::log::alevel::all);
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
// Initialize Asio
echo_server.init_asio();
// Register our message handler
echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2));
// Listen on port 9002
echo_server.listen(9002);
// Start the server accept loop
echo_server.start_accept();
// Start the ASIO io_service run loop
echo_server.run();
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
} catch (...) {
std::cout << "other exception" << std::endl;
}
}
详情可以参考:https://hpg123.blog.csdn.net/article/details/124888325文章来源:https://www.toymoban.com/news/detail-651932.html
3.2 使用crow库
corw是一个开源、轻量化的c++web库,在使用上与python的flask是类似的,其支持路由绑定、返回数据(json、文本、response对象(静态资源、模板文件)、接口请求处理(REST请求,url参数绑定、json请求、GET参数和POST
参数)和各种高级操作(Cookie操作、Session操作、文件上传操作、文件下载操作、websocket
操作、自定义loghandler)。此外,还对各类参数请求、结果返回过程中对中文的支持(如get
参数、post参数、url参数、json结果中中文参数的正确解读)。其使用文档的下载地址为:https://download.csdn.net/download/a486259/87471152文章来源地址https://www.toymoban.com/news/detail-651932.html
#include "crow.h"
#include <unordered_set>
#include <mutex>
int main()
{
crow::SimpleApp app;
std::mutex mtx;
std::unordered_set<crow::websocket::connection*> users;
CROW_WEBSOCKET_ROUTE(app, "/ws")
.onopen([&](crow::websocket::connection& conn) {
CROW_LOG_INFO << "new websocket connection from " << conn.get_remote_ip();
std::lock_guard<std::mutex> _(mtx);
users.insert(&conn);
})
.onclose([&](crow::websocket::connection& conn, const std::string& reason) {
CROW_LOG_INFO << "websocket connection closed: " << reason;
std::lock_guard<std::mutex> _(mtx);
users.erase(&conn);
})
.onmessage([&](crow::websocket::connection& /*conn*/, const std::string& data, bool is_binary){
std::lock_guard<std::mutex> _(mtx);
//给当前用户发信息
conn.send_text(data);
//给所有用户发信息
for (auto u : users){
if (is_binary){
u->send_binary(data);
}else{
u->send_text(data);
});
CROW_ROUTE(app, "/")
([] {
char name[256];
gethostname(name, 256);
crow::mustache::context x;
x["servername"] = name;
auto page = crow::mustache::load("ws.html");
return page.render(x);
});
}
到了这里,关于C++下轻量化websocket客户端库——easywsclient的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!