前言
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的接口,肯定沒問題,所以這個效果也不是很明顯,但流程很清晰。
結束語
處於不同的境界,看到不同的層面,我現在就是這個感覺。加油ヾ(◍°∇°◍)ノ゙