c++ websocket简单讲解
只做简单讲解。
一.定义和原理
WebSocket 是从 HTML5 开始⽀持的⼀种⽹⻚端和服务端保持⻓连接的消息推送机制,传统的 web 程序都是属于 "⼀问⼀答" 的形式,即客⼾端给服务器发送了⼀个 HTTP 请求,服务器给客⼾端返回⼀个 HTTP 响应。这种情况下服务器是属于被动的⼀⽅,如果客⼾端不主动发起请求服务器就⽆法主动给客⼾端响应。
WebSocket 更接近于 TCP 这种级别的通信⽅式,⼀旦连接建⽴完成客⼾端或者服务器都可以主动的向对⽅发送数据。WebSocket 协议本质上是⼀个基于 TCP 的协议。为了建⽴⼀个 WebSocket 连接,客⼾端浏览器⾸先 要向服务器发起⼀个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了⼀些附加头信息,通过 这个附加头信息完成握⼿过程并升级协议的过程。
首先先经过TCP三次握手,然后再通过HTTP协议发送更新协议请求,最终切换为websocket协议进行通信。
WebSocketpp同时⽀持HTTP和Websocket两种⽹络协议。
二.搭建服务器简易流程
由于库里的接口服务器过于复杂,需要的请查看⽤⼾⼿册: http://docs.websocketpp.org/。
重要的接口在下面用到讲解。
int main()
{ //1. 实例化server对象
wsserver_t wssrv;
//2. 设置日志等级
wssrv.set_access_channels(websocketpp::log::alevel::none);
//3. 初始化asio调度器
wssrv.init_asio();
wssrv.set_reuse_addr(true);
//4. 设置回调函数
wssrv.set_open_handler(std::bind(wsopen_callback, &wssrv, std::placeholders::_1));
wssrv.set_http_handler(std::bind(http_callback, &wssrv, std::placeholders::_1));
wssrv.set_message_handler(std::bind(wsmsg_callback, &wssrv, std::placeholders::_1,
wssrv.set_close_handler(std::bind(wsclose_callback, &wssrv, std::placeholders::_1));
std::placeholders::_2));
//5. 设置监听端口
wssrv.listen(8085);
//6. 开始获取新连接
wssrv.start_accept();
//7. 启动服务器
wssrv.run();
return 0;
}
四个回调函数分别为: websocket握⼿成功回调处理函数,http请求回调处理函数,websocket消息回调处理函数,websocket连接关闭回调处理函数。在对应的事件触发后自动调用。
三.简单服务器的搭建
编写一个简单服务器,对浏览器的请求返回一个简单的http界面。代码如下:
#include <iostream>
#include <string>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
typedef websocketpp::server<websocketpp::config::asio> wsserver_t;
void print(const std::string &str)
{
std::cout << str << std::endl;
}
void http_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
//给客户端返回一个hello world的页面
wsserver_t::connection_ptr conn = srv->get_con_from_hdl(hdl);
std::cout << "body: " << conn->get_request_body() << std::endl;
websocketpp::http::parser::request req = conn->get_request();
std::cout << "method: " << req.get_method() << std::endl;
std::cout << "uri: " << req.get_uri() << std::endl;
std::string body = "<html><body><h1>Hello World</h1></body></html>";
conn->set_body(body);
conn->append_header("Content-Type", "text/html");
conn->set_status(websocketpp::http::status_code::ok);
// wsserver_t::timer_ptr tp = srv->set_timer(5000, std::bind(print, "bitejiuyeke"));
// tp->cancel();//定时任务的取消,会导致定时任务立即被执行
}
void wsopen_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
std::cout << "websocket握手成功!!\n";
}
void wsclose_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {
std::cout << "websocket连接断开!!\n";
}
void wsmsg_callback(wsserver_t *srv, websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg) {
wsserver_t::connection_ptr conn = srv->get_con_from_hdl(hdl);
std::cout << "wsmsg: " << msg->get_payload() << std::endl;
std::string rsp = "client say: " + msg->get_payload();
conn->send(rsp, websocketpp::frame::opcode::text);
}
int main()
{
//1. 实例化server对象
wsserver_t wssrv;
//2. 设置日志等级
wssrv.set_access_channels(websocketpp::log::alevel::none);
//3. 初始化asio调度器
wssrv.init_asio();
wssrv.set_reuse_addr(true);
//4. 设置回调函数
wssrv.set_http_handler(std::bind(http_callback, &wssrv, std::placeholders::_1));
wssrv.set_open_handler(std::bind(wsopen_callback, &wssrv, std::placeholders::_1));
wssrv.set_close_handler(std::bind(wsclose_callback, &wssrv, std::placeholders::_1));
wssrv.set_message_handler(std::bind(wsmsg_callback, &wssrv, std::placeholders::_1, std::placeholders::_2));
//5. 设置监听端口
wssrv.listen(8085);
//6. 开始获取新连接
wssrv.start_accept();
//7. 启动服务器
wssrv.run();
return 0;
}