Qt写websocketpp服务端

时间:2023-03-10 01:27:32
Qt写websocketpp服务端

1、下载websocketpp,地址为https://github.com/zaphoyd/websocketpp,版本为0.7。

2、下载boost,地址为https://www.boost.org/,版本为1.6.3。

3、说明:websocketpp并不是必须需要boost,如果C++编译为C11以上,是可以不用的。

4、Qt创建一个console工程(如:websocketServer),将下载下来的websocket_master里面的websocket文件夹放到该工程目录下,在webSocketServer.pro文件中添加include(websocket/websocket.pri),

5、创建websocket_server类,头文件websocket_server.h内容如下:

#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>

#include <websocketpp/impl/connection_impl.hpp>
#include <websocketpp/config/core.hpp>
#include <websocketpp/connection.hpp>
#include <websocketpp/endpoint.hpp>
#include <websocketpp/close.hpp>
#include <websocketpp/uri.hpp>

#include <map>
#include <string>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <QDateTime>

using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
using websocketpp::endpoint;
using websocketpp::connection;

typedef websocketpp::server<websocketpp::config::asio> server;
typedef server::message_ptr message_ptr;
/////////////////////////////////////////////////////////////////////
class connection_metadata
{
public:
typedef websocketpp::lib::shared_ptr<connection_metadata> ptr;
connection_metadata(websocketpp::connection_hdl hdl,std::string strRemote) :
m_hdl(hdl),strRemote(strRemote)
{}

    void setDateTime()
{
dt = QDateTime::currentDateTime();
}
    QDateTime getDateTime() const
{
return dt;
}
    void sethdl(websocketpp::connection_hdl hdl)
{
m_hdl = hdl;
}
    websocketpp::connection_hdl gethdl()
{
return m_hdl;
}
    void update_time()
{
dt = QDateTime::currentDateTime();
}
    void setRemote(std::string strRemote)
{
this->strRemote = strRemote;
} std::string getRemote() const
{
return strRemote;
}
private:
QDateTime dt;
std::string strRemote;
websocketpp::connection_hdl m_hdl;
};
/////////////////////////////////////////////////////////////////////
class websocket_server
{
public:
websocket_server();
~websocket_server(); static void on_open(server* s,websocket_server* pWebSocket,websocketpp::connection_hdl hdl);
static void on_close(server* s,websocket_server* pWebSocket,websocketpp::connection_hdl hdl);
static void on_message(server* s,websocket_server* pWebSocket,websocketpp::connection_hdl hdl,message_ptr msg);
    void start(int port);
private:
typedef std::map<std::string,connection_metadata::ptr> con_list; server echo_server;
con_list m_connection_list;
    websocketpp::lib::shared_ptr<websocketpp::lib::thread> m_thread;
};

6、websocket_server.cpp内容如下:

websocket_server::websocket_server()
{
m_connection_list.clear();
}
websocket_server::~websocket_server()
{
for(con_list::iterator iter = m_connection_list.begin();iter != m_connection_list.end();)
{
echo_server.close(iter->second->gethdl(),websocketpp::close::status::going_away,"");
m_connection_list.erase(iter++);
}
    echo_server.stop_perpetual();
m_thread->join();
}
//连接
void websocket_server::on_open(server *s,websocket_server* pWebSocket,websocketpp::connection_hdl hdl)
{
server::connection_ptr con = s->get_con_from_hdl(hdl);
const std::string strRemote = con->get_remote_endpoint();
con_list::iterator iter = pWebSocket->m_connection_list.find(strRemote);
    if(iter == pWebSocket->m_connection_list.end())
{
connection_metadata* pmetadata = new connection_metadata(hdl,strRemote);
pWebSocket->m_connection_list.insert(make_pair(strRemote,pmetadata));
}
else
{
iter->second->sethdl(hdl);
}
}
//断开
void websocket_server::on_close(server* s,websocket_server* pWebSocket,websocketpp::connection_hdl hdl)
{
server::connection_ptr con = s->get_con_from_hdl(hdl);
const std::string strRemote = con->get_remote_endpoint();
con_list::iterator iter = pWebSocket->m_connection_list.find(strRemote);
    if(iter != pWebSocket->m_connection_list.end())
{
pWebSocket->m_connection_list.erase(iter);
}
}
//通信
void websocket_server::on_message(server* s,websocket_server* pWebSocket,websocketpp::connection_hdl hdl, message_ptr msg)
{
if(msg->get_opcode() == websocketpp::frame::opcode::text)
{
server::connection_ptr con = s->get_con_from_hdl(hdl);
const std::string strRemote = con->get_remote_endpoint();
     std::cout << strRemote <<std::endl;
}
    std::cout << "on_message called with hdl: " << hdl.lock().get() << " and message: " << msg->get_payload() << std::endl;

    if(msg->get_payload() == "stop-listening")
{
s->stop_listening();
return;
} try
{
s->send(hdl, msg->get_payload(),msg->get_opcode());//接收到的数据原路返回
}
    catch (const websocketpp::lib::error_code& e)
{
std::cout << "Echo failed because: " << e << "(" << e.message() << ")" << std::endl;
}
}
void websocket_server::start(int port)
{
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();
echo_server.start_perpetual();
        echo_server.set_open_handler(bind(&on_open,&echo_server,this,::_1));
echo_server.set_close_handler(bind(&on_close,&echo_server,this,::_1));
echo_server.set_message_handler(bind(&on_message,&echo_server,this,::_1,::_2));
        // Listen on port 9002
echo_server.listen(port);
        // Start the server accept loop
echo_server.start_accept();
        // Start the ASIO io_service run loop
//echo_server.run();
m_thread = websocketpp::lib::make_shared<websocketpp::lib::thread>(&server::run,&echo_server);//用线程m_thread的run函数来跑echo_server的run,这样可以避免程序卡在echo_server的run里
}
catch (websocketpp::exception const & e)
{
std::cout << e.what() << std::endl;
}
catch (...)
{
std::cout << "other exception" << std::endl;
}
}