swoole.websocket.Connect建議定義;每個客戶端都會先建立握手,這里是必經之處。比如在這里記錄你自己程序用戶與客戶端的連接ID(fd)等。
swoole.websocket.Test是自定義的test消息接收事件,該類事件定義的事件類 是用于接收客戶端發送過來的消息并自行處理后續邏輯。該類事件可以定義任意個,比如一個項目可以有聊天、客服、直播等多種實時通訊場景,你可以分別定義不同的事件來分開處理不同場景的邏輯業務。
操作說明:
Connect事件中的KaTeX parse error: Undefined control sequence: \\Request at position 10: event是app\\?R?e?q?u?e?s?t?請求對象 Test自定義消息接…event是客戶端發送過來的消息
\\think\\Swoole\\Websocket類對象方法:
broadcast 設置進行廣播消息發送
isBroadcast 判斷當前是否是廣播模式
to 設置收件人fd或聊天室名(可以數組設置多個)
getTo 獲取收件人fd或聊天室名
join 當前客戶端加入到指定聊天室(可以多個)
leave 當前客戶端離開指定聊天室(可以多個)
emit 消息發送
close 關閉當前連接
getSender 獲取當前客戶端id(即fd)
setSender 設置發件人的fd
\\think\\swoole\\Manager類對象方法:
getServer 獲取當前Swoole的服務對象,利用該對象直接操作原生Swoole服務方法
stop 停止服務
app\\listener\\WsConnect 中的測試代碼

客戶端
~~~
<html>
<head></head>
<body>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
接收者<input type="text" id="fid">
發送內容<input type="text" id="content">
<button onclick="aaa()">發送</button>
<script>ip
var ws = new WebSocket("ws://ip:端口/");
ws.onopen = function () {
console.log('lianjiezhong')
};
ws.onclose = function () {
console.log("lianjieguanbi")
};
ws.onmessage = function (evt) {
console.log(evt)
};
function aaa(){
var fid = $("#fid").val();
var content = $("#content").val();
ws.send(JSON.stringify(['test',{
to:fid,
aa:content
}]));
}
</script>
</body>
</html>
~~~
服務端接收并返回
~~~
<?php
declare (strict_types = 1);
namespace app\listener;
class WsTest
{
/**
* 事件監聽處理
*
* @return mixed
*/
public function handle($event)
{
$ws = app('think\swoole\Websocket');
//發送指定客戶端,包括發送者自己
//to 也可以是一個數據,發送給多個人
//testcall 自定義事件名稱
$ws -> to(intval($event['to'])) ->emit('testcall',[
'form' =>[
'id' => 88,
'name' => "劉備"
],
'to' => [
'id' => 99,
'name' => "張飛"
],
'message' => [
'id' => 100,
'createtime' => "1000-3-5",
'message' => $event['aa']
]
]);
}
}
~~~
~~~
//廣播,發送給所有人, 但不發送給自己
// 自定義事件名, 接收發送內容
$ws ->broadcast()->emit('gb',$event['aa']);
//模擬發送 模擬2 給3 發送信息,其實是1發的
//setSender 模擬誰
$ws -> setSender(2) -> to(3) -> emit('mn',$event['aa']);
//因為think-swoole 有一些方法并沒有包含所有的swoole,那么怎么才能獲得
//swoole本身的方法呢?如下
//1. 直接獲取
$ser1 = app('swoole.server');
//2. 通過Manager 管理類獲取
$ser2 = app('think\swoole\Manager')->getServer();
//驗證類是否相同
var_dump(get_class($ser1));
var_dump(get_class($ser2));
//接下來就可以用swoole本身的一些方法了,并不局限于think-swoolele
//可以用什么方法具體看swoole手冊
驗證結果
~~~

## 客戶端回調
必須注意的地方是最后發送消息的send方法,由于think-swoole中是按照socketio進行解析發送過來的數據,所以你發送的數據應該是”\[‘事件名’, 真正要發送的數據\]”的字符串形式:第一個參數的test就是對應服務器端的Test事件,用于區分更多場景的實時通信邏輯業務;第二個參數才是你真正發送的數據可以是字符串、數據、對象,服務器端$event參數獲取的就是它。
需要注意的是返回的字符串并不是直接的JSON字符串。前面多了一個42( socketio 的2個狀態碼),你需要自行通過JS匹配出第一個“\[”字符的位置(str.indexOf(‘\[’))然后截取(str.substr(start, end))出來才可以獲取到JSON對象。你可以通過返回JSON的第一個值(事件名)判斷出對應到什么場景的業務。
下面代碼實例客戶端處理數據
~~~
<html>
<head></head>
<body>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
接收者<input type="text" id="fid">
發送內容<input type="text" id="content">
<button onclick="aaa()">發送</button>
<script>
var ws = new WebSocket("ws://ip:端口/");
ws.onopen = function () {
console.log('lianjiezhong')
};
ws.onclose = function () {
console.log("lianjieguanbi")
};
ws.onmessage = function (evt) {
// console.log(evt.data)
call_message(evt.data)
};
//處理回調參數
function call_message(data){
//處理回調數據
console.log(data);
var start;
var start_arr = data.indexOf('[');
var start_json = data.indexOf('{');
if(start_arr < 0){
start = start_json;
}
if(start_arr >= 0 && start_json >= 0){
start = Math.min(start_arr,start_json);
}
if(start){
var json = JSON.parse(data.substr(start));
if (json instanceof Array){
window[json[0]](json[1])
}
}
}
function testcall(message){
console.log(message);
}
function aaa(){
var fid = $("#fid").val();
var content = $("#content").val();
ws.send(JSON.stringify(['test',{
to:fid,
aa:content
}]));
}
</script>
</body>
</html>
~~~