webscoket绑定php uid,Think-Swoole之WebSocket客户端消息解析与使用SocketIO处理用户UID与fd关联...
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 app\listener;
class WsConnect
{
/**
* 事件監(jiān)聽(tīng)處理
*
* @return mixed
* 受用 WebSocket 客戶端連接入口
*/
public function handle($event)
{
//實(shí)例化 Websocket 類(lèi)
$ws = app('\think\swoole\Websocket');
//
$ws -> emit('sendfd',$ws -> getSender());
}
}
app/listener/WsTest.php<?php
declare (strict_types = 1);
namespace app\listener;
use \think\swoole\Websocket;
class WsTest
{
/**
* 事件監(jiān)聽(tīng)處理
*
* @return mixed
*/
public function handle($event,Websocket $ws)
{
$ws -> to(intval($event['to'])) -> emit('testcallback',$event['message']);
}
}
客戶端執(zhí)行上述兩個(gè)事件后,控制臺(tái)打印出以下信息:
返回信息前面有一些數(shù)字,40、42都代表什么意義呢?
因?yàn)槲覀兪褂玫臄U(kuò)展是基于 SocketIO 協(xié)議的,這些數(shù)字可以理解為協(xié)議的代號(hào)。
打開(kāi) /vendor/topthink/think-swoole/src/websocket/socketio/Packet.php ,有以下內(nèi)容:
上面是 Socket 類(lèi)型,下面是引擎,前后兩個(gè)代號(hào)上下拼湊得到:40:”MESSAGE CONNECT”
42:”MESSAGE EVENT”
結(jié)合這些代碼,能知道 SocketIO 中消息的大體運(yùn)作情況。
通過(guò)控制臺(tái)打印出的消息,我們發(fā)現(xiàn)這些消息不能直接拿到使用,需要進(jìn)行截取處理:
test.html
Document消息:
接收者:
發(fā)送
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('連接斷開(kāi)');
}
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ù)] 這種格式
}
解析后的數(shù)據(jù):
使用 SocketIO 處理消息業(yè)務(wù)
SocketIO 的相關(guān)知識(shí)可以查看文檔,重點(diǎn)看客戶端方面知識(shí):
https://www.w3cschool.cn/socket/socket-k49j2eia.html
iotest.html
Document消息:
接收者:
發(fā)送
//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
})
}
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 app\listener;
class WsConnect
{
/**
* 事件監(jiān)聽(tīng)處理
*
* @return mixed
* 受用 WebSocket 客戶端連接入口
*/
public function handle($event)
{
//實(shí)例化 Websocket 類(lèi)
$ws = app('\think\swoole\Websocket');
//
$ws -> emit('sendfd',$ws -> getSender());
}
}
app/listener/WsTest.php<?php
declare (strict_types = 1);
namespace app\listener;
use \think\swoole\Websocket;
class WsTest
{
/**
* 事件監(jiān)聽(tīng)處理
*
* @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']
]
]);
}
}
開(kāi)啟兩個(gè)客戶端,fd 分別是5、6:
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ā)送信息:
兩個(gè)客戶端均會(huì)受到信息:
可見(jiàn)消息已經(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.htmlvar ws = new WebSocket("ws://127.0.0.1:9501/?uid=1");
iotest.htmlvar socket = io("http://127.0.0.1:9501?uid=1", {transports: ['websocket']});
后端可以在連接事件中進(jìn)行綁定:
app/listener/WsConnect.php<?php
declare (strict_types = 1);
namespace app\listener;
class WsConnect
{
/**
* 事件監(jiān)聽(tīng)處理
*
* @return mixed
* 受用 WebSocket 客戶端連接入口
*/
public function handle($event)
{
// $event 為請(qǐng)求對(duì)象
//實(shí)例化 Websocket 類(lèi)
$ws = app('\think\swoole\Websocket');
//獲取 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ù),連接斷開(kāi)后再清空用戶對(duì)因的 fd。假如服務(wù)器重啟,那么二者的對(duì)應(yīng)關(guān)系也就沒(méi)用了,所以不必存入數(shù)據(jù)庫(kù),存入 Redis 最好,通過(guò) Redis 的 Hash 來(lái)映射二者關(guān)系也是不錯(cuò)的選擇。
與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖總結(jié)
以上是生活随笔為你收集整理的webscoket绑定php uid,Think-Swoole之WebSocket客户端消息解析与使用SocketIO处理用户UID与fd关联...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: xp装完就蓝屏怎么办 遇到装完XP就蓝屏
- 下一篇: php html url编码,html中