今天我們會稍微討論一下 websocket 跟 http 連線不太一樣的地方,接下來會把 websocket 拆成兩種類別的連線以便之後開發便利
在昨天的 client.py
範例裡,我們可以看到 client.py
是開始發送封包的一方
# client.py: in hello()
await websocket.send(name)
greeting = await websocket.recv()
# server.py: in hello()
name = await websocket.recv()
await websocket.send(greeting)
這邊可以看到 send(), recv() 幾乎都是成對出現,因為送出資料之後,也會期待收到結果。這就是 HTTP 最常看到的 request/response 的連線模式。
假如我們換成 HTTP 的話,會發現 send(), recv() 的動作在一個函式呼叫中就結束了。從這裡可以看出來 websocket 有一個比較不利的缺點,就是寫法相比於 HTTP API 比較零碎、冗長。
# client.py
import requests
response = requests.get(url)
所以接下來我們的改進措施就是讓 websocket 可以用比較固定的連線模式開發新功能
這種模式基本上就是從上面的範例衍生,也就是 send(), recv() 成對出現。
REQ 端/主動發起:先 send() 再 recv()
RES 端/被動回應:先 recv() 再 send()
懸念:假設有兩組 REQ1/RES1,REQ2/RES2,假設有封包傳進 websocket,那我們要怎麼知道應該用 RES1 還是 RES2 來處理呢?關於這個懸念,先賣個關子,明天我們再針對這個問題討論
SUB 端:只做 recv()
PUB 端:只做 send()
其實這就是大名鼎鼎的訂閱/發布模式,會這樣子切是為了簡化 websocket 連線的複雜度,讓連線程式變得更好理解、更好實作/維護
這些端點只要做好一件事(收/發),剩下的部分就靠這些基本模式組合了
我們雖然享受 websocket 帶來的全雙工、彈性和自由,但其實只要加上一些約束,我們可以讓 websocket 發揮它更大的功用