前言
WebSocket 是一个基于 Web 的协议,旨在使 client 应用程序和远程主机之间进行双向通信。如果最初的握手成功,则两个实体可以来回发送数据。WebSocket 是通过用更少的网络延迟和最小数据交换来努力获取实时数据的应用程序解决方案。
——摘自 一去丶二三里
在项目中使用WebSocket,一般建立的是长链接,而为了实现实时数据的交流,则需要双方一直连接,即使中途发生意外,也需再次连接。故在此介绍一下自动连接的思路。
WebSocket理论介绍
WebSocket是出自协议HTML5,使在控制环境下运行不受信任代码的客户端和能够选择与那些代码通信的远程主机之间能够双向通信(即全双工)。协议包含打开握手,其次是基本消息框架,在TCP之上。这项技术的目的是为基于浏览器的、需要与服务器双向通信的应用程序提供一种不依赖于打开多个HTTP连接的机制。
WebSocket比之前的ajax轮询和阻塞型好很多,节省很多资源,不用占用不必要的资源。Websocket为了兼容现有的HTTP基础设施,故WebSocket握手沿用了部分HTTP握手,即在其基础上进行了升级(以下握手资源代码来源网络):
请求握手
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
接收请求
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
这个消息结构很神似HTTP的,我们根据Upgrade 和 Connection两个字段可清楚的看出这是升级版的,用的是WebSocket协议。
思路介绍
为了实现自动连接,我通过一个定时器,当断开一小段时间,然后再次尝试连接;如果成功则结束,若失败则重复上述步骤。若长时间没连接上,可停止尝试,通知服务台,当可以时,可请求主动连接。。只不过我考虑到如果频繁的请求连接,可能误认为攻击,故我将其每次失败后再次尝试连接的时间段加长。
代码示例
.h文件
private slots:
void onConnected();
void onDisconnected();
void reconnect();
void on_disconnectButton_clicked();
void on_connectButton_clicked();
private:
QWebSocket* m_pWebSocket;
QTimer* m_pTimer;
.cpp文件
构建函数中初始化,并连接
m_pTimer=new QTimer(this);
m_pWebSocket=new QWebSocket;
QUrl url("ws://121.40.165.18:8800");
m_pWebSocket->open(url);
connect(m_pWebSocket,SIGNAL(connected()),this,SLOT(onConnected()));
connect(m_pWebSocket,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
connect(m_pTimer,SIGNAL(timeout()),this,SLOT(reconnect()));
一系列连接、断开、重连 信号槽
void MainWindow::onConnected()
{
QString text=ui->textBrowser->toPlainText();
text+="connect successful\n";
ui->textBrowser->setText(text);
delaySec=1;
m_pTimer->stop();
}
void MainWindow::onDisconnected()
{
QString text=ui->textBrowser->toPlainText();
text+="disconnected\n";
ui->textBrowser->setText(text);
m_pTimer->start(delaySec*1000);
delaySec<<=1;
if(delaySec>60){
m_pTimer->stop();
delaySec=1;
QMessageBox::information(this,QStringLiteral("websocket连接状态"),
QStringLiteral("无法连接webscoket,请联系后台!"));
}
}
void MainWindow::reconnect()
{
QString text=ui->textBrowser->toPlainText();
text+="reconnect\n";
ui->textBrowser->setText(text);
m_pWebSocket->abort();
m_pWebSocket->open(QUrl("ws://121.40.165.18:8800"));
}
void MainWindow::on_disconnectButton_clicked()
{
QString text=ui->textBrowser->toPlainText();
text+="request disconnect\n";
ui->textBrowser->setText(text);
m_pWebSocket->close();
}
void MainWindow::on_connectButton_clicked()
{
reconnect();
}
注意:在实际项目中,服务器崩了,这个流程好像有点问题,我觉一个open对应一个close。话说回来,如果服务器崩了,一切都没得玩了,开着界面也无用,所以,可以考虑直接关闭。
效果图
由于,网上给的websocket的接口,肯定没问题,所以这个效果也不是很明显,但流程很清晰。
结束语
处于不同的境界,看到不同的层面,我现在就是这个感觉。加油ヾ(◍°∇°◍)ノ゙