C++利用第三方通信库hvlib实现websocket通信

  • Post author:
  • Post category:其他


hvlib是一个第三方库,里面包含各种通信协议,利用库可以很方便的实现网络通信,下面是利用hvlib实现的websocket通信
hvlib源码地址:https://download.csdn.net/download/Pailugou/64827333?spm=1001.2014.3001.5503
hvlib编译库64位:https://download.csdn.net/download/Pailugou/64827902?spm=1001.2014.3001.5503
服务端代码实现:
#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;

	//第二个参数为:0直接内部开启单独线程,不阻塞主线程的运行
	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将数据回调到界面,然后要用信号在转发一下,以队列的方式连接,不然会出现崩溃的现象



版权声明:本文为Pailugou原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。