微信小程序中如何使用WebSocket實現長連接(含完整源碼)

本文由騰訊雲技術團隊原創,感謝作者的分享。

1、前言

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

微信小程序提供了一套在微信上運行小程序的解決方案,有比較完整的框架、組件以及 API,在這個平臺上面的想象空間很大。騰訊雲研究了一番之後,發現微信支持 WebSocket 還是很值得玩味的。這個特性意味著我們可以做一些實時同步或者協作的小程序。

這篇文章分享了一個基於WebSocket長連接的微信小程序——簡單的剪刀石頭布小遊戲的製作過程,希望能對想要在微信小程序中使用 WebSocket 的開發者有所幫助。

說明:本文完整源碼請從文末附件下載:http://www.52im.net/thread-1703-1-1.html)

2、相關文章

《新手入門貼:史上最全Web端即時通訊技術原理詳解》

《Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE》

《新手快速入門:WebSocket簡明教程》

《WebSocket詳解(一):初步認識WebSocket技術》

《WebSocket詳解(二):技術原理、代碼演示和應用案例》

《WebSocket詳解(三):深入WebSocket通信協議細節》

《WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)》

《WebSocket詳解(五):刨根問底HTTP與WebSocket的關係(下篇)》

《WebSocket詳解(六):刨根問底WebSocket與Socket的關係》

《socket.io實現消息推送的一點實踐及思路》

《Web端即時通訊技術的發展與WebSocket、Socket.io的技術實踐》

《Web端即時通訊安全:跨站點WebSocket劫持漏洞詳解(含示例代碼)》

《開源框架Pomelo實踐:搭建Web端高性能分佈式IM聊天服務器》

《使用WebSocket和SSE技術實現Web端消息推送》

《詳解Web端通信方式的演進:從Ajax、JSONP 到 SSE、Websocket》

《MobileIMSDK-Web的網絡層框架為何使用的是Socket.io而不是Netty?》

《理論聯繫實際:從零理解WebSocket的通信原理、協議格式、安全性》

>> 更多同類文章 ……

3、運行效果

整個遊戲非常簡單,連接到服務器後自動匹配在線玩家(沒有則分配一個機器人),然後兩人進行剪刀石頭布的對抗遊戲。當對方進行拳頭選擇的時候,頭像會旋轉,這個過程使用 WebSocket 會變得簡單快速。

剪刀石頭布遊戲效果如下圖所示:

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

4、為什麼要用 WebSocket

使用傳統的 HTTP 輪詢或者長連接的方式也可以實現類似服務器推送的效果,但是這類方式都存在資源消耗過大或推送延遲等問題(詳見文章《新手入門貼:史上最全Web端即時通訊技術原理詳解》)。而 WebSocket 直接使用 TCP 連接保持全雙工的傳輸,可以有效地減少連接的建立,實現真正的服務器通信,對於有低延遲有要求的應用是一個很好的選擇。

目前瀏覽器對 WebSocket 的支持程度已經很好,加上微信小程序的平臺支持,這種可以極大提高客戶端體驗的通信方式將會變得更加主流。

Server 端需要實現 WebSocket 協議,才能支持微信小程序的 WebSocket 請求。鑑於 SocketIO 被廣泛使用(詳見《Socket.IO介紹:支持WebSocket、用於WEB端的即時通訊的框架》),剪刀石頭布的小程序,我們選用了比較著名的SocketIO 作為服務端的實現。

Socket IO 的使用比較簡單,僅需幾行代碼就可啟動服務。

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

export class Server {

init(path: string) {

/** Port that server listen on */

this.port = process.env.PORT;

/** HTTP Server instance for both express and socket io */

this.http = http.createServer();

/** Socket io instance */

this.io = SocketIO(this.http, { path });

/** Handle incomming connection */

this.io.on("connection", socket => {

// handle connection

});

}

start() {

this.http.listen(this.port);

console.log(`---- server started. listen : ${this.port} ----`);

}

}

const server = new

Server();

server.init("/applet/ws/socket.io");

server.start();

但是,SocketIO 和一些其它的服務器端實現,都有其配套的客戶端來完成上層協議的編碼解碼。但是由於微信的限制(不能使用 window 等對象), SocketIO 的客戶端代碼在微信小程序平臺上是無法運行的。

經過對 SocketIO 通信進行抓包以及研究其客戶端源碼,筆者封裝了一個大約 100 行適用於微信小程序平臺的 WxSocketIO類,可以幫助開發者快速使用 SocketIO 來進行 WebSocket 通信。

1

2

3

const socket = new WxSocketIO();

socket.on('hi', packet => console.log('server say hi: ' + packet.message));

socket.emit('hello', { from: 'techird' });

如果想要使用微信原生的 API,那麼在服務器端也可以直接使用 ws 來實現 W3C 標準的接口。不過 SocketIO 支持多進程的特性,對於後續做橫向擴張是很有幫助的。騰訊雲在後面也會有計劃推出支持大規模業務需求的 WebSocket 連接服務,減小業務的部署成本。

5、通信協議設計

實現一個多客戶端交互的服務,是需要把中間涉及到所有的消息類型都設計清楚的,就像是類似剪刀石頭布這樣一個小程序,都有下面這些消息類型。

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

具體每個消息的參數可以參考源碼裡的server/protocol.brief.md

6、服務器邏輯

服務器的邏輯很簡單:

  • 收到用戶請求加入房間(join),就尋找還沒滿的房間:
  • - 找到房間,則加入;
  • - 沒找到房間,創建新房間。
  • 有用戶加入的房間檢查是否已滿,如果已滿,則:
  • - 給房間裡每個用戶發送開始遊戲的信號(start);
  • - 啟動計時器,計時器結束後進行遊戲結算。
  • 遊戲結算:
  • - 兩兩之間 PK,贏方分數加一,輸方減一,最終得每個玩家基本得分 x;
  • - 對於每個玩家,如果分數 x 大於 0,則視為勝利,連勝次數加一,否則連勝次數歸零;
  • - 本局得分為分數 x 乘以連勝次數。
  • 發送本局遊戲結果給房間裡的每位玩家。

微信小程序直接使用上面的協議,針對不同的場景進行渲染。整體的狀態機如下。

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

狀態機整理清楚後,就是根據狀態機來控制什麼時候發送消息,接到消息後如何處理的問題了。具體實現請參照 app/pages/game/game.js裡的源碼。

7、部署和運行

拿到了本小程序源碼的朋友可以嘗試自己運行起來(完整源碼請從文末附件下載)。

7.1整體架構

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

小程序的架構非常簡單,這裡有兩條網絡同步,一條是 HTTPS 通路,用於常規請求。對於 WebSocket 請求,會先走 HTTPS 後再切換協議到 WebSocket 的 TCP 連接,從而實現全雙工通信。

7.2準備域名和證書

在微信小程序中,所有的網絡請求受到嚴格限制,不滿足條件的域名和協議無法請求,具體包括:

  • 只允許和在 MP 中配置好的域名進行通信,如果還沒有域名,需要註冊一個;
  • 網絡請求必須走 HTTPS 協議,所以你還需要為你的域名申請一個證書;
  • 域名註冊好之後,可以登錄微信公眾平臺配置通信域名了。

設置域名和證書如下圖所示:

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

7.3雲主機和鏡像部署

剪刀石頭布的服務器運行代碼和配置已經打包成騰訊雲 CVM 鏡像,大家可以直接使用。

騰訊雲用戶可以免費領取禮包,體驗騰訊雲小程序解決方案。

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

▲ 設置鏡像

鏡像已包含「剪刀石頭布」和「小相冊」兩個小程序的服務器環境與代碼,需要體驗兩個小程序的朋友無需重複部署。

7.4配置 HTTPS

鏡像中已經部署了nginx,需要在/etc/nginx/conf.d下修改配置中的域名、證書、私鑰。

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

▲ Nginx 中配置證書

配置完成後,即可啟動 nginx。

7.5域名解析

我們還需要添加域名記錄解析到我們的雲服務器上,這樣才可以使用域名進行 HTTPS 服務。

在騰訊雲註冊的域名,可以直接使用雲解析控制檯來添加主機記錄,直接選擇上面購買的 CVM。

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

▲ 修改 DNS 記錄

解析生效後,我們在瀏覽器使用域名就可以進行 HTTPS 訪問。

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

▲ HTTPS 效果

7.6啟動 WebSocket 服務

在鏡像的 nginx 配置中(/etc/nginx/conf.d),已經把 /applet/websocket的請求轉發到http://127.0.0.1:9595 處理。我們需要把 Node 實現的 WebSocket 服務在這個端口裡運行起來。

進入鏡像中源碼位置:

cd /data/release/qcloud-applet-websocket

使用pm2 啟動服務:

pm2 start process.json

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

在微信開發者工具中修改小程序源碼中的 config.js 配置,把通訊域名修改成上面申請的域名。完成後點擊調試即可連接到 WebSocket 服務進行遊戲。

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

配置完成後,運行小程序就可以看到成功搭建的提示!

微信小程序中如何使用WebSocket實現長連接(含完整源碼)

▲ 成功效果

8、附件下載(完整源碼)

http://www.52im.net/thread-1703-1-1.html


分享到:


相關文章: