websocketppwebsocket++库教程服务端代码封装websocketpp这个库是开源的,我在项⽬中引⽤,感觉还是把代码开源出来给需要的⼈⽐较好。我⾃⼰对这个库进⾏了简单的封装,可以做出动态库或者so库,使⽤起来也⽅便。之所有要这么封装还是因为把这个websocketpp库引⼊我们的项⽬后会报xtime命名冲突,实在没办法解决,所有重新封装了⼀层,彻底屏蔽websocketpp库的头⽂件,这样引⼊项⽬后就不会冲突了。我只提供封装后的代码,⾄于websocket库的编译和项⽬配置需要⾃⼰去做。
web_sock_server.h头⽂件
#pragma once
#include "pch.h"
#include <string>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#if defined(_WIN32) || defined(_WIN64)
# define WEB_SOCKET_DLL_EXPORT __declspec(dllexport)
#else
# define WEB_SOCKET_DLL_EXPORT
#endif
enum WsOpcode
{
BINARY = 1,
TEXT,
OTHER
};
//定义回调函数
typedef boost::function<void(void*, const std::string, WsOpcode)> OnMessageFun;//接收消息到来的函数
typedef boost::function<void(void*)> OnOpenFun; //连接到来
typedef boost::function<void(void*, std::string)> OnCloseFun; //连接断开的函数
//单例的服务器
class WEB_SOCKET_DLL_EXPORT WebSockServer
{
private:
WebSockServer();
webserver接口开发public:
static WebSockServer& Instance();
bool Init(uint16_t uPort, OnOpenFun openFun, OnCloseFun closeFun, OnMessageFun msgFun, void* pOiService = nullptr); /*
如果调⽤StartServer,应该另开⼀个线程来调⽤,因为程序会在⾥⾯循环运⾏,不会返回,直到另⼀个线程调⽤StopServer函数 */
bool StartServer();
void StopServer();
void StopListening();
/*
发送数据的接⼝
pClient为客户端标识
data 为要发送的数据
*/
bool Send(void* pClient, const std::string data, WsOpcode opcode = WsOpcode::BINARY);
void Close(void* pClient);
void CloseAll();
//private:
// void ThreadProccess(); //线程函数
public:
OnOpenFun m_onOpenFun;
OnCloseFun m_onCloseFun;
OnMessageFun m_onMsgFun;
private:
//boost::thread * m_threadMain; //websock 的循环线程
bool m_bServerStart; //服务是否启动的标志
};
web_sock_server.cpp源⽂件
#include "web_sock_server.h"
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <map>
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
typedef server::message_ptr message_ptr;
typedef std::map<void*, websocketpp::connection_hdl> ClientMap;
static server g_server;//全局的websocket服务器
//递交给上层的不能直接递交websocketpp::connection_hdl类型,因为上层没有这个类型的定义,因此⽤另外的类型(void*)来唯⼀标识⼀个客户端//并且在本地维护⼀个客户端标识到对应实际客户端对象的映射,
static ClientMap g_mapClient;
static boost::shared_mutex rwMutext;
typedef boost::shared_lock<boost::shared_mutex> ReadLock;
typedef boost::unique_lock<boost::shared_mutex> WriteLock;
// Define a callback to handle incoming messages
static void on_message(WebSockServer* pWebserver, websocketpp::connection_hdl hdl, message_ptr msg) {
//std::cout << "on_message called with hdl: " << hdl.lock().get()
/
/ << " and message: " << msg->get_payload()
// << std::endl;
//回调上层
if (!pWebserver->pty())
{
WsOpcode opcode = WsOpcode::OTHER;
if (msg->get_opcode() == websocketpp::frame::opcode::value::TEXT)
{
opcode = WsOpcode::TEXT;
}
else if (msg->get_opcode() == websocketpp::frame::opcode::value::BINARY)
{
opcode = WsOpcode::BINARY;
}
pWebserver->m_onMsgFun(hdl.lock().get(), msg->get_payload(), opcode);
}
}
static void on_open(WebSockServer* pWebserver, websocketpp::connection_hdl hdl)
{
//std::cout << "client opend:" << hdl.lock().get() << std::endl;
//写锁
WriteLock writeLock(rwMutext);
/
/加⼊缓存
g_mapClient.insert(std::pair<void*, websocketpp::connection_hdl>(hdl.lock().get(), hdl));
//回调上层
if (!pWebserver->pty())
{
pWebserver->m_onOpenFun(hdl.lock().get());
}
}
static void on_close(WebSockServer* pWebserver, websocketpp::connection_hdl hdl)
{
//std::cout << "client close:" << hdl.lock().get() << std::endl;
/
/回调上层
if (!pWebserver->pty())
{
pWebserver->m_onCloseFun(hdl.lock().get(), "");
}
//写锁
WriteLock writeLock(rwMutext);
const ClientMap::iterator it = g_mapClient.find(hdl.lock().get());
//删除缓存
if (it != d())
{
ase(it);
return;
}
}
WebSockServer::WebSockServer()
{
m_bServerStart = false;
//m_threadMain = nullptr;
}
WebSockServer& WebSockServer::Instance()
{
static WebSockServer instance;
return instance;
}
bool WebSockServer::Send(void* pClient, const std::string data, WsOpcode opcode) {
//读锁
ReadLock readLock(rwMutext);
//先在本地查对应的客户端对象
const ClientMap::iterator it = g_mapClient.find(pClient);
if (it == d())
{
return false;
}
websocketpp::connection_hdl hdl = it->second;
std::error_code ec;
websocketpp::frame::opcode::value sCode = websocketpp::frame::opcode::BINARY;
if (opcode == TEXT)
{
sCode = websocketpp::frame::opcode::TEXT;
}
g_server.send(hdl, data.c_str(), data.size(), sCode, ec);//发送⼆进制数据
//检查错误信息
if (ec.value() == 0)
{
return true;
}
else
{
return false;
}
}
void WebSockServer::Close(void* pClient)
{
//写锁
WriteLock writeLock(rwMutext);
//先在本地查对应的客户端对象
const ClientMap::iterator it = g_mapClient.find(pClient);
if (it == d())
{
//std::cout << "can not find client. " << (int)pClient << std::endl;
return;
}
websocketpp::connection_hdl hdl = it->second;
g_server.close(hdl, (websocketpp::close::status::value)0, "");
//从映射中删除
ase(it);
}
void WebSockServer::CloseAll()
{
//写锁
WriteLock writeLock(rwMutext);
for (auto it = g_mapClient.begin(); it != d(); it++)
{
//关闭所有连接
websocketpp::connection_hdl hdl = it->second;
g_server.close(hdl, (websocketpp::close::status::value)0, "");
}
//清空缓存
g_mapClient.clear();
}
bool WebSockServer::Init(uint16_t uPort, OnOpenFun openFun, OnCloseFun closeFun, OnMessageFun msgFun, void* pOiService) {
m_onOpenFun = openFun;
m_onCloseFun = closeFun;
m_onMsgFun = msgFun;
try {
// Set logging settings
g_server.set_access_channels(websocketpp::log::alevel::none);
g_server.clear_access_channels(websocketpp::log::alevel::none);
// Initialize Asio
if (pOiService == nullptr)
{
g_server.init_asio();
}
else
{
g_server.init_asio((boost::asio::io_service*)pOiService);
}
// Register our message handler
g_server.set_message_handler(bind(&on_message, this, ::_1, ::_2));
g_server.set_close_handler(bind(&on_close, this, ::_1));
g_server.set_open_handler(bind(&on_open, this, ::_1));
g_server.set_reuse_addr(true);
// Listen port
g_server.listen(websocketpp::lib::asio::ip::tcp::v4(), uPort);
// Start the server accept loop
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论