提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、接口认识
- 二、搭建websocketpp服务器
- 0.重定义server类型
- 1.实例化服务器对象
- 2.初始化日志输出
- 3.初始化asio框架
- 4.设置回调函数
- 5.设置地址重用,设置监听端口,开始监听
- 6.启动服务器
前言
概念:是一个应用层的tcp长连接协议。
搭建一个websocket服务器其实就是搭建了一个tcp服务器,只不过应用层使用websocket协议
格式进行数据处理。
在IM项目中:
客户端 -----HTTP----- 服务器
但是在聊天室项目中,不单单是请求-响应的业务处理,还包含了数据的主动推送
而这种消息数据的主动推送,是HTTP协议无法实现的。
因此需要搭建一个长连接的服务器,用于主动向客户端推送数据。
选择websocket协议的考虑:因为HTTP通信支持websocket协议的切换
websocketpp底层网络通信是依靠的boost中的asio异步机制实现的.
一、接口认识
有一个endpoint类,这个类中提供了一些接口,包括设置四种回调函数,设置日志打印等级,
还有获取connection_hdl对应的连接。初始化asio框架,启动地址服用,设置监听端口,启动故服务器。
namespace websocketpp {
typedef lib::weak_ptr<void> connection_hdl;
template <typename config>
class endpoint : public config::socket_type {typedef typename connection_type::ptr connection_ptr;
typedef typename connection_type::message_ptr message_ptr;typedef lib::function<void(connection_hdl)> open_handler;
typedef lib::function<void(connection_hdl)> close_handler;
typedef lib::function<void(connection_hdl)> http_handler;
typedef lib::function<void(connection_hdl,message_ptr)> message_handler;/* websocketpp::log::alevel::none 禁止打印所有日志*/
void set_access_channels(log::level channels);/*设置日志打印等级*//*设置指定事件的回调函数*/
void set_open_handler(open_handler h);/*websocket 握手成功
回调处理函数*/
void set_close_handler(close_handler h);/*websocket 连接关
闭回调处理函数*/
void set_message_handler(message_handler h);/*websocket 消
息回调处理函数*/
void set_http_handler(http_handler h);/*http 请求回调处理函数*//*获取 connection_hdl 对应连接的 connection_ptr*/
connection_ptr get_con_from_hdl(connection_hdl hdl);
/*websocketpp 基于 asio 框架实现,init_asio 用于初始化 asio 框架中的 io_service 调度器*/
void init_asio();/*设置是否启用地址重用*/
void set_reuse_addr(bool value);/*设置 endpoint 的绑定监听端口*/
void listen(uint16_t port);};
还有一个server类,这个类继承了endpoint类,也就拥有了上面的函数,所以我们搭建服务器主要是使用Server类。
class server : public endpoint<connection<config>,config> {
/*初始化并启动服务端监听连接的 accept 事件处理*/
void start_accept();
};
二、搭建websocketpp服务器
0.重定义server类型
因为server类是带有模板参数的,类型很长,这里我们typedef以下,方便我们使用
typedef websocketpp::server<websocketpp::config::asio> server_t;
1.实例化服务器对象
创建一个server对象
server_t server;
2.初始化日志输出
关闭websocketpp的日志输出
server.set_access_channels(websocketpp::log::alevel::none);
3.初始化asio框架
前面也说了,websocketpp底层网络通信是依靠boost的asio异步通信机制实现的。
server.init_asio();
4.设置回调函数
这里有一个需要介绍的是,消息处理回调函数的设置,我们使用了bind,绑定了server对象进去。因为在消息处理回调函数中我们需要使用server对象获取到连接,使用连接来对数据进行响应。
server.set_open_handler(onOpen);server.set_close_handler(onClose);auto msg_hadler = std::bind(onMessage, &server, std::placeholders::_1, std::placeholders::_2);server.set_message_handler(msg_hadler);
这里是设置的回调函数,这里的形参websocketpp::connection_hdl hdl它是一个weak_ptr,我们需要使用server中的一个函数get_con_from_hdl来获取到connection_ptr对象,这是一个shared_ptr,在这个对象里面有一个函数send可以进行响应发送。
可以看到,send需要填写两个参数,一个是响应正文,还有一个则是响应真正文的类型,我们这里填写的是文本类型,在项目中我们使用protobuf对正文进行序列化,因此需要使用binary类型。
还有一个需要介绍的是我们需要使用message_ptr中的get_payload()函数获取消息正文。
void onOpen(websocketpp::connection_hdl hdl) {std::cout << "websocket长连接建立成功!\n";
}
void onClose(websocketpp::connection_hdl hdl) {std::cout << "websocket长连接断开!\n";}
void onMessage(server_t *server, websocketpp::connection_hdl hdl, server_t::message_ptr msg) {//1. 获取有效消息载荷数据,进行业务处理std::string body = msg->get_payload();std::cout << "收到消息:" << body << std::endl;//2. 对客户端进行响应//获取通信连接auto conn = server->get_con_from_hdl(hdl);//发送数据conn->send(body + "-Hello!", websocketpp::frame::opcode::value::text);
}
5.设置地址重用,设置监听端口,开始监听
websocketpp不想httplib,设置监听后并没有开启监听,还需要手动开启监听。
// 5. 启用地址重用server.set_reuse_addr(true);// 5. 设置监听端口server.listen(9090);// 6. 开始监听server.start_accept();
6.启动服务器
server.run();