websocket初始化
前言
上一集我们HTTP的ping操作就可以跑通了,那么我们还有一个协议---websocket,我们在这一集就要去完成我们websocket的初始化。
分析
我们在初始化websocket的之前,我们考虑一下,我们什么时候就要初始化我们的websocket?
我们是不是应该在程序一启动,我们就和我们的websocket的服务端那边建立连接?
那么我们就需要把初始化websocket的方法直接放在我们NetClient的构造函数当中,只要我们一创建一个NetClient就会直接初始化我们的websocket。
客户端
initWebsocket
我们初始化websocket需要考虑的只有两个因素。
第一,websocket的五种信号的处理,我们需要使用信号槽对五种信号进行处理。
第二,我们需要连接服务器。
我们的五种信号为:
- 建立连接之后connected
- 断开连接之后disconnected
- 连接出错的情况 errorOccurred
- 收到 文本消息 textMessageReceived
- 收到二进制消息 binaryMessageReceived
cpp
void NetClient::initWebsocket()
{
//信号槽
connect(&webSocketClient, &QWebSocket::connected, this, [=](){
LOG() <<"websocket 连接成功!";
});
connect(&webSocketClient, &QWebSocket::disconnected, this, [=](){
LOG() <<"websocket 连接断开!";
});
connect(&webSocketClient, &QWebSocket::errorOccurred, this, [=](QAbstractSocket::SocketError error){
LOG() <<"websocket 连接失败! 错误原因:" << error;
});
connect(&webSocketClient, &QWebSocket::textMessageReceived, this, [=](const QString& message){
LOG() <<"websocket 收到文本消息!message=" << message;
});
connect(&webSocketClient, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& byteArray){
LOG() <<"websocket 收到二进制消息! length:" << byteArray.length();
//todo:
});
//服务器连接
webSocketClient.open(WEBSOCKET_URL);
}
这里我们二进制就只打印长度,后续还有内容需要完成,先不讲。
服务端
我们的服务端的websocket也是需要单例模式,提醒一下,我们是持久化的连接的哦!
我们在构造函数里,给websocket设置服务器的名字,以及让websocket的安全模式设置为非安全模式。意味着这个 WebSocket 服务器不会使用加密连接(即不使用 WSS,而是使用 WS)。如果你需要加密连接,可以使用 QWebSocketServer::SecureMode
,但这通常需要额外的配置,比如 SSL/TLS 证书。
cpp
class WebsocketServer : public QObject{
Q_OBJECT
private:
static WebsocketServer* instance;
WebsocketServer()
: websocketServer("websocket server", QWebSocketServer::NonSecureMode)
{}
QWebSocketServer websocketServer;
public:
static WebsocketServer* getInstance();
bool init();
};
init
我们需要用信号槽来建立我们的新连接。新连接之后我们就获取到用来通信的socket对象,之后我们还是像客户端的代码有四种信号。我们最后需要绑定端口启动我们的服务,当然我们监听的是我们的8001的端口号,这个也是我们在NetClient里面规定的。
cpp
bool WebsocketServer::init()
{
//信号槽
connect(&websocketServer, &QWebSocketServer::newConnection, this, [=](){
//连接建立成功
qDebug() << "[websocket] 连接建立成功!";
//获取到用来通信的socket对象
QWebSocket* socket = websocketServer.nextPendingConnection();
//剩余信号处理
connect(socket, &QWebSocket::disconnected, this, [=](){
qDebug() << "[websocket] 连接断开!";
});
connect(socket, &QWebSocket::errorOccurred, this, [=](QAbstractSocket::SocketError error){
qDebug() << "[websocket] 连接失败! 错误原因" << error;
});
connect(socket, &QWebSocket::textMessageReceived, this, [=](const QString& message){
qDebug() << "[websocket] 收到文本数据!message=" << message;
});
connect(socket, &QWebSocket::binaryMessageReceived, this, [=](const QByteArray& byteArray){
qDebug() << "[websocket] 收到二进制数据! length=" << byteArray.length();
});
});
//绑定端口启动服务
bool ok = websocketServer.listen(QHostAddress::Any, 8001);
return ok;
}
测试
cpp
WebsocketServer* websocketServer = WebsocketServer::getInstance();
if(!websocketServer->init()){
qDebug() << "websocket 服务器启动失败!";
return 1;
}
qDebug() << "websocket 服务器启动成功!";
cpp
NetClient::NetClient(model::DataCenter *dataCenter)
:dataCenter(dataCenter)
{
initWebsocket();
}
这样,我们先启动服务端,再启动客户端就可以自动连接我们的websocket了。
看看我们的测试结果。
那么我们就完成了这一集的任务,那么我们期待下一集!