socket 傳送陣列_讓 WebSocket 更友好:給 Hyperf 加上 socket.io 支援
技術標籤:socket 傳送陣列
有小夥伴抱怨道,WebSocket Server感覺太原始,沒有“框架感”。
Http 是一個表達能力非常豐富的協議。除了Header,Body等基本定義外,通過一系列RFC,它還帶來了一些廣泛接受的規範,比如querystring是怎麼劃分的,formdata是什麼樣的,multipart又是什麼樣的。基於這些規範,框架可以靈活的設計路由器、控制器、請求物件、響應物件等等。
我們今天討論的主角,WebSocket協議,雖然也是建立在Http之上,但是卻沒有定義Frame的內容應該是什麼樣的。
Frame裡可以是JSON:
{"event": "orderCreated", "data":{"orderId": 123}}
也可以是字串
orderCreated|orderId:123
還可以是二進位制
0101010101010101
所以作為框架來講,處理WebSocket是沒有抓手的。有點類似於封裝TCP Server,只能做到管理連線建立和關閉這樣的顆粒度,Frame裡的資訊只能黑箱處理。於是小夥伴在用WebSocket Server時,便會覺得沒有Http Server封裝度高。
當我們對Frame約定一個結構時,框架就大有可為了。
http://Socket.io就是一套非常流行的WebSocket應用層協議。(http://Socket.io不止於WebSocket,不過在2020年的今天,不支援WebSocket的瀏覽器基本絕跡,其他XHR Polling等方式也就邊緣化了)。
我們先過於簡略地來看一下http://Socket.io協議。
0 是連線建立。
1 是連線關閉。
2 是天王蓋地虎 (ping)
3 是寶塔鎮河妖 (pong)
4 是傳遞資訊。
傳遞資訊時又要細分。
42 是一條新資訊。
43 是一條回覆資訊。
42123 是一條id為123的資訊。
43123 是對剛才123號資訊的回覆。
傳送資訊時,內容是一個JSON陣列,陣列第一個引數固定是事件名。 比如
42123["orderCreated", {"orderId": 123}]
約定了如上的基本結構,框架就有發揮空間了。
在Hyperf1.1.30版本中,你可以這樣建立一個http://Socket.io服務。
<?php
/**
* @SocketIONamespace("/")
*/
class WebSocketController extends BaseNamespace
{
/**
* @Event("event")
* @param string $data
*/
public function onEvent(Socket $socket, $data)
{
// 應答
return 'Event Received: ' . $data;
}
/**
* @Event("join-room")
* @param string $data
*/
public function onJoinRoom(Socket $socket, $data)
{
// 將當前使用者加入房間
$socket->join($data);
// 向房間內其他使用者推送(不含當前使用者)
$socket->to($data)->emit('event', $socket->getSid() . "has joined {$data}");
// 向房間內所有人廣播(含當前使用者)
$this->emit('event', 'There are ' . count($socket->getAdapter()->clients($data)) . " players in {$data}");
}
/**
* @Event("say")
* @param string $data
*/
public function onSay(Socket $socket, $data)
{
$data = Json::decode($data);
$socket->to($data['room'])->emit('event', $socket->getSid() . " say: {$data['message']}");
}
}
我們可以看到,支援的功能豐富多了,可以通過@Event()
註解進行事件的分發,在控制器裡通過return
來對事件進行ACK,實現房間分組、廣播、私聊等等。
還有一點這裡沒有體現。藉助Redis PubSub,hyperf/socketio-server元件還封裝了跨機器的實時通訊,開箱就是分散式。
詳細的功能清單,可以查閱1.1.30版本的Hyperf文件,這裡就不再贅述了。
希望http://Socket.io協議的支援,可以讓WebSocket更好用,不再有開篇提到的困惑。