最新文章專題視頻專題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

Think-Swoole之WebSocket客戶端消息解析與使用SocketIO處理用戶UID與fd關(guān)聯(lián)

來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-02 18:01:55
文檔

Think-Swoole之WebSocket客戶端消息解析與使用SocketIO處理用戶UID與fd關(guān)聯(lián)

Think-Swoole之WebSocket客戶端消息解析與使用SocketIO處理用戶UID與fd關(guān)聯(lián):WebSocket 客戶端消息的解析前面我們演示了當(dāng)客戶端連接服務(wù)端,會(huì)觸發(fā)連接事件,事件中我們要求返回當(dāng)前客戶端的 fd。當(dāng)客戶端發(fā)送消息給服務(wù)端,服務(wù)端會(huì)根據(jù)我們的規(guī)則將消息發(fā)送給指定 fd 的客戶端:app/listener/WsConnect.php<php
推薦度:
導(dǎo)讀Think-Swoole之WebSocket客戶端消息解析與使用SocketIO處理用戶UID與fd關(guān)聯(lián):WebSocket 客戶端消息的解析前面我們演示了當(dāng)客戶端連接服務(wù)端,會(huì)觸發(fā)連接事件,事件中我們要求返回當(dāng)前客戶端的 fd。當(dāng)客戶端發(fā)送消息給服務(wù)端,服務(wù)端會(huì)根據(jù)我們的規(guī)則將消息發(fā)送給指定 fd 的客戶端:app/listener/WsConnect.php<php

WebSocket 客戶端消息的解析

前面我們演示了當(dāng)客戶端連接服務(wù)端,會(huì)觸發(fā)連接事件,事件中我們要求返回當(dāng)前客戶端的 fd。當(dāng)客戶端發(fā)送消息給服務(wù)端,服務(wù)端會(huì)根據(jù)我們的規(guī)則將消息發(fā)送給指定 fd 的客戶端:

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace applistener;
class WsConnect
{
 /**
 * 事件監(jiān)聽處理
 *
 * @return mixed
 * 受用 WebSocket 客戶端連接入口
 */
 public function handle($event)
{
 //實(shí)例化 Websocket 類
 $ws = app('	hinkswooleWebsocket');
 //
 $ws -> emit('sendfd',$ws -> getSender());
 }
}

app/listener/WsTest.php

<?php
declare (strict_types = 1);
namespace applistener;
use 	hinkswooleWebsocket;
class WsTest
{
 /**
 * 事件監(jiān)聽處理
 *
 * @return mixed
 */
 public function handle($event,Websocket $ws)
{
 $ws -> to(intval($event['to'])) -> emit('testcallback',$event['message']);
 }
}

客戶端執(zhí)行上述兩個(gè)事件后,控制臺(tái)打印出以下信息:

3e65bb5742e35710db2e3ae1e9bba30.png

返回信息前面有一些數(shù)字,40、42都代表什么意義呢?

因?yàn)槲覀兪褂玫臄U(kuò)展是基于 SocketIO 協(xié)議的,這些數(shù)字可以理解為協(xié)議的代號(hào)。

打開 /vendor/topthink/think-swoole/src/websocket/socketio/Packet.php ,有以下內(nèi)容:

ac3e617f79cdf6b208b304f2ca64911.png

上面是 Socket 類型,下面是引擎,前后兩個(gè)代號(hào)上下拼湊得到:

40:”MESSAGE CONNECT”
42:”MESSAGE EVENT”

結(jié)合這些代碼,能知道 SocketIO 中消息的大體運(yùn)作情況。

通過(guò)控制臺(tái)打印出的消息,我們發(fā)現(xiàn)這些消息不能直接拿到使用,需要進(jìn)行截取處理:

test.html

<!DOCTYPE HTML>
<html>
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
消息:<input type="text" id="message">
接收者:<input type="text" id="to">
<button onclick="send()">發(fā)送</button>
<script>
 var ws = new WebSocket("ws://127.0.0.1:9501/");
 ws.onopen = function(){
 console.log('連接成功');
 }
 //數(shù)據(jù)返回的解析
 function mycallback(data){
 var start = data.indexOf('[') // 第一次出現(xiàn)的位置
 var start1 = data.indexOf('{')
 if(start < 0){
 start = start1;
 }
 if(start >= 0 && start1 >= 0){
 start = Math.min(start,start1);
 }
 if(start >= 0){
 console.log(data);
 var json = data.substr(start); //截取
 var json = JSON.parse(json);
 console.log(json);
 }
 }
 ws.onmessage = function(data){
 // console.log(data.data);
 mycallback(data.data);
 }
 ws.onclose = function(){
 console.log('連接斷開');
 }
 function send()
{
 var message = document.getElementById('message').value;
 var to = document.getElementById('to').value;
 console.log("準(zhǔn)備給" + to + "發(fā)送數(shù)據(jù):" + message);
 ws.send(JSON.stringify(['test',{
 to:to,
 message:message
 }])); //發(fā)送的數(shù)據(jù)必須是 ['test',數(shù)據(jù)] 這種格式
 }
</script>
</body>
</html>

解析后的數(shù)據(jù):

d049d27768d703d197019f59ceac116.png

使用 SocketIO 處理消息業(yè)務(wù)

SocketIO 的相關(guān)知識(shí)可以查看文檔,重點(diǎn)看客戶端方面知識(shí):

https://www.w3cschool.cn/socket/socket-k49j2eia.html

iotest.html

<!DOCTYPE HTML>
<html>
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
消息:<input type="text" id="message">
接收者:<input type="text" id="to">
<button onclick="send()">發(fā)送</button>
<script src="./socketio.js"></script>
<script>
 //http 協(xié)議
 var socket = io("http://127.0.0.1:9501", {transports: ['websocket']});
 socket.on('connect', function(){
 console.log('connect success');
 });
 socket.on('close',function(){
 console.log('connect close')
 });
 //send_fd 為自定義的場(chǎng)景值,和后端對(duì)應(yīng)
 socket.on("sendfd", function (data) {
 console.log(data)
 });
 //testcallback 為自定義的場(chǎng)景值,和后端對(duì)應(yīng)
 socket.on("testcallback", function (data) {
 console.log(data)
 });
 function send() {
 var message = document.getElementById('message').value;
 var to = document.getElementById('to').value;
 socket.emit('test', {
 //屬性可自行添加
 to:to,
 message:message
 })
 }
</script>
</body>
</html>

var socket = io("http://127.0.0.1:9501", {transports: ['websocket']}); 中第二個(gè)參數(shù)指明要升級(jí)的協(xié)議。

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace applistener;
class WsConnect
{
 /**
 * 事件監(jiān)聽處理
 *
 * @return mixed
 * 受用 WebSocket 客戶端連接入口
 */
 public function handle($event)
{
 //實(shí)例化 Websocket 類
 $ws = app('	hinkswooleWebsocket');
 //
 $ws -> emit('sendfd',$ws -> getSender());
 }
}

app/listener/WsTest.php

<?php
declare (strict_types = 1);
namespace applistener;
use 	hinkswooleWebsocket;
class WsTest
{
 /**
 * 事件監(jiān)聽處理
 *
 * @return mixed
 */
 public function handle($event,Websocket $ws)
{
// $ws -> to(intval($event['to'])) -> emit('testcallback',$event['message']);
 $ws -> to(intval($event['to'])) -> emit('testcallback',[
 'form' => [
 'id' => 10,
 'fd' => $ws -> getSender(),
 'nickname' => '張三'
 ],
 'to' => [
 'id' => 11,
 'fd' => intval($event['to']),
 'nickname' => '李四'
 ],
 'massage' => [
 'id' => 888,
 'create_time' => '2020-03-13',
 'content' => $event['message']
 ]
 ]);
 }
}

開啟兩個(gè)客戶端,fd 分別是5、6:

a15a44c4dc464e480664ac7add1efb2.png

WsConnect.php 中,有 $ws -> emit('sendfd',$ws -> getSender()); 發(fā)送 fd 消息對(duì)應(yīng)的場(chǎng)景值是 “sendfd” ,在 iotest.html 中,有socket.on("sendfd", function (data) {console.log(data)}); 這段代碼,其中也有場(chǎng)景值 “sendfd”,這行代碼可以直接獲取對(duì)應(yīng)場(chǎng)景值的信息,所以控制臺(tái)上會(huì)打印出 fd 值。

用 fd 5 向 fd 6 發(fā)送信息:

73542665974ef733eb1a7afd192a7f5.png

兩個(gè)客戶端均會(huì)受到信息:

1752f5ebc05df83efbe7fc07a0c55f8.png

可見消息已經(jīng)經(jīng)過(guò)解析,因?yàn)?WsTest.php 中 發(fā)送消息指定場(chǎng)景值 testcallback,iotest.html 中通過(guò) socket.on("testcallback", function (data){console.log(data)}); 可直接獲取解析過(guò)的結(jié)果。

這就看出了 SocketIO 在客戶端消息接收方面的便捷之處了。

用戶 UID 和客戶端 fd 的綁定

前面的例子中,都是通過(guò)指定 fd 來(lái)向客戶端發(fā)送消息,實(shí)際場(chǎng)景中,我們不可能通過(guò) fd 確定發(fā)送對(duì)象,因?yàn)?fd 不是固定不變的,因此需要將用戶的 UID 與客戶端的 fd 進(jìn)行綁定,進(jìn)而可以通過(guò)選擇用戶,來(lái)確定 fd 完成消息的發(fā)送。

只需要將前端頁(yè)面的 HTTP 連接中增加 UID 參數(shù)即可:

test.html

var ws = new WebSocket("ws://127.0.0.1:9501/?uid=1");

iotest.html

var socket = io("http://127.0.0.1:9501?uid=1", {transports: ['websocket']});

后端可以在連接事件中進(jìn)行綁定:

app/listener/WsConnect.php

<?php
declare (strict_types = 1);
namespace applistener;
class WsConnect
{
 /**
 * 事件監(jiān)聽處理
 *
 * @return mixed
 * 受用 WebSocket 客戶端連接入口
 */
 public function handle($event)
{
 // $event 為請(qǐng)求對(duì)象
 //實(shí)例化 Websocket 類
 $ws = app('	hinkswooleWebsocket');
 //獲取 uid
 $uid = $event -> get('uid');
 //獲取 fd
 $fd = $ws -> getSender();
 //獲取到 uid 和 fd 后,可以存數(shù)據(jù)庫(kù),內(nèi)存或者 redis
 $ws -> emit('sendfd',[
 'uid' => $uid,
 'fd' => $fd
 ]);
 }
}

有了 UID 與 fd ,可以在每次連接成功后,更新數(shù)據(jù)庫(kù),連接斷開后再清空用戶對(duì)因的 fd。假如服務(wù)器重啟,那么二者的對(duì)應(yīng)關(guān)系也就沒用了,所以不必存入數(shù)據(jù)庫(kù),存入 Redis 最好,通過(guò) Redis 的 Hash 來(lái)映射二者關(guān)系也是不錯(cuò)的選擇。

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文檔

Think-Swoole之WebSocket客戶端消息解析與使用SocketIO處理用戶UID與fd關(guān)聯(lián)

Think-Swoole之WebSocket客戶端消息解析與使用SocketIO處理用戶UID與fd關(guān)聯(lián):WebSocket 客戶端消息的解析前面我們演示了當(dāng)客戶端連接服務(wù)端,會(huì)觸發(fā)連接事件,事件中我們要求返回當(dāng)前客戶端的 fd。當(dāng)客戶端發(fā)送消息給服務(wù)端,服務(wù)端會(huì)根據(jù)我們的規(guī)則將消息發(fā)送給指定 fd 的客戶端:app/listener/WsConnect.php<php
推薦度:
標(biāo)簽: 消息 用戶 客戶端
  • 熱門焦點(diǎn)

最新推薦

猜你喜歡

熱門推薦

專題
Top