hvlib是一个第三方库,里面包含各种通信协议,利用库可以很方便的实现网络通信,下面是利用hvlib实现的websocket通信
hvlib源码地址:https:
hvlib编译库64位:https:
服务端代码实现:
#pragma once
#include "WebSocketServer.h"
#include "hssl.h"
#include "WebSocket.h"
#include "EventLoop.h"
#include "htime.h"
#include <functional>
using namespace hv;
class HVWebSocket
{
public:
explicit HVWebSocket(const int port);
~HVWebSocket();
void sendMsg(const std::string Msg);
std::function<void(std::string)> m_pMsgCallBack;
private:
void openWebSocket(const WebSocketChannelPtr& channel, const std::string& req);
void onMessage(const WebSocketChannelPtr& channel, const std::string& msg);
void onClose(const WebSocketChannelPtr& channel);
void serverRun();
void timerCallBack(TimerID id);
private:
int m_iPort;
WebSocketService m_ws;
websocket_server_t m_wst;
WebSocketChannelPtr m_channelPtr;
std::function<void(TimerID)> m_pTimerCallBack;
};
#include "HVWesocket.h"
HVWebSocket::HVWebSocket(const int port)
: m_iPort(port)
{
m_ws.onopen = std::bind(&HVWebSocket::openWebSocket, this, std::placeholders::_1, std::placeholders::_2);
m_ws.onmessage = std::bind(&HVWebSocket::onMessage, this, std::placeholders::_1, std::placeholders::_2);
m_ws.onclose = std::bind(&HVWebSocket::onClose, this, std::placeholders::_1);
m_pTimerCallBack = std::bind(&HVWebSocket::timerCallBack, this, std::placeholders::_1);
this->serverRun();
}
HVWebSocket::~HVWebSocket()
{
m_pMsgCallBack = nullptr;
m_channelPtr->close();
}
void HVWebSocket::openWebSocket(const WebSocketChannelPtr& channel, const std::string& str)
{
std::cout << "onopen: Get " << str << std::endl;
m_channelPtr = channel;
setInterval(1000, m_pTimerCallBack);
}
void HVWebSocket::onMessage(const WebSocketChannelPtr& channel, const std::string& str)
{
std::cout << "服务端收到消息:" << str << std::endl;
if (m_pMsgCallBack)m_pMsgCallBack(str);
}
void HVWebSocket::onClose(const WebSocketChannelPtr& channel)
{
channel->close();
}
void HVWebSocket::serverRun()
{
m_wst.port = m_iPort;
m_wst.ws = &m_ws;
websocket_server_run(&m_wst, 0);
if (m_pMsgCallBack)m_pMsgCallBack("服务开启...");
}
void HVWebSocket::sendMsg(const std::string msg)
{
m_channelPtr->send(msg);
}
void HVWebSocket::timerCallBack(TimerID id)
{
if (m_channelPtr->isConnected())
{
char time[DATETIME_FMT_BUFLEN] = { 0 };
datetime_t datetime = datetime_now();
datetime_fmt(&datetime, time);
m_channelPtr->send(time);
}
else
{
killTimer(id);
}
}
客户端实现代码:
#pragma once
#include "WebSocketClient.h"
using namespace hv;
class WebClient
{
public:
explicit WebClient(const int port, const std::string host = "127.0.0.1");
void sendMsg(std::string msg);
void close();
std::function<void(std::string)> m_pMsgCallBack;
private:
void onClose();
void onOpen();
void onMsg(const std::string& msg);
private:
WebSocketClient* m_client;
int m_port;
std::string m_hostAdress;
};
#include "WebClient.h"
WebClient::WebClient(const int port, const std::string host)
: m_port(port)
, m_hostAdress(host)
{
m_client = new WebSocketClient();
m_client->onopen = std::bind(&WebClient::onOpen, this);
m_client->onmessage = std::bind(&WebClient::onMsg, this, std::placeholders::_1);
m_client->onclose = std::bind(&WebClient::onClose, this);
std::string url = "ws://" + host + ":" + std::to_string(port) + "/echo";
m_client->open(url.c_str());
}
void WebClient::onMsg(const std::string& msg)
{
std::cout << "客户端收到消息:" << msg << std::endl;
if (m_pMsgCallBack)m_pMsgCallBack(msg);
}
void WebClient::onClose()
{
std::cout << "WS client closeed" << std::endl;
}
void WebClient::onOpen()
{
std::cout << "WS client opened" << std::endl;
if (m_pMsgCallBack)m_pMsgCallBack(u8"客户端开启...");
}
void WebClient::sendMsg(const std::string msg)
{
if (m_client)m_client->send(msg);
}
void WebClient::close()
{
if (m_client)m_client->close();
m_pMsgCallBack = nullptr;
}
如果使用Qt作为前段界面,在使用function将数据回调到界面,然后要用信号在转发一下,以队列的方式连接,不然会出现崩溃的现象