[TOC]
## 說明:
插件是基于`workerman`實現的websocket即時通訊。
`workerman`文檔地址:https://www.workerman.net/doc/workerman/
最早本來是想基于[https://www.workerman.net/phpsocket_io](https://www.workerman.net/phpsocket_io)實現通訊,但是由于PHP版本問題(我們需要高版本環境下開發)有較大兼容問題,而該擴展本身又不再更新。因此自己做了一個簡單以事件為驅動的websocket通訊用于滿足開主業務開發過程中需要websocket即時通訊輔助開發。
所以你的主業務只要不是即時通訊類工具,可以考慮使用該插件;否則,建議使用其他成熟方案。
該插件只提供通訊服務,具體業務需自己整合和開發。
WOOAdmin官方嚴正聲明: 為配合國家打擊跨境賭博、電信詐騙、斷卡行動,本站所有源碼僅限中國大陸區域使用且使用站點要通過ICP備案,否則一律上報至公安機關!
## 安裝和啟動:
1、安裝`workerman`
~~~
composer require workerman/workerman
~~~
2、下載并解壓到addons目錄下
3、后臺開發管理->插件管理中,找到“websocket”插件點擊安裝
4、新增命令:在`config/console.php`新增一個ws的命令
~~~
'ws' => 'addons\websocket\service\command\Ws'
~~~
5、命令:
~~~
php think ws start -m // 啟動服務
php think ws stop -m // 停止服務
php think ws restart -m // 重啟服務
~~~
## 配置:
`config/websocket.php`下:
~~~
<?php
return [
'worker_name' => 'WebsocketWorker',//設置當前Worker實例的名稱,方便運行status命令時識別進程
'daemonize' => true,// 此屬性為全局靜態屬性,表示是否以daemon(守護進程)方式運行
'log_file' => runtime_path() . 'websocket.log',
'pid_file' => runtime_path() . 'websocket.pid',
'count' => 1, //設置當前Worker實例啟動多少個進程 https://www.workerman.net/doc/workerman/worker/count.html
'server' => env('WS_SERVER', 'websocket://0.0.0.0:8282'),
'client' => env('WS_CONNECT_HOST', 'ws://127.0.0.1:8282'),
'listen_strict' => true,// true 就是所有事件都必須注冊
'check_origin' => false,
// 注冊工作類
'worker' => [
'demo' => [
'handler' => app\common\worker\Demo::class,
'listen' => [ // listen_strict true:就所有事件都要注冊,否則可以不注冊
'initMessage' => 'initMessage',
'mySend' => 'mySend'// 自定義事件
]
]
]
];
~~~
`server`:啟動端口,如果本地和服務器不一樣可以在.end中`WS_SERVER`定義
`client`:客戶端鏈接地址
`worker`:所有工作類和事件都要在這里面的進行注冊
## 后端服務工作類
~~~
<?php
declare (strict_types = 1);
namespace app\common\worker;
use addons\websocket\service\WebSocketManager;
use Workerman\Connection\TcpConnection;
class Demo extends WebSocketManager
{
public function onConnect(TcpConnection $connection)
{
$params = $connection->requestParams ?? [];
$this->send($connection, 'myConnect', 'success', '鏈接成功', ['id' => $connection->id, 'params' => $params]);
}
public function mySend(TcpConnection $connection, $event, $data)
{
$this->send($data['clientId'], 'myReceive', 'success', '成功', ['fromId' => $connection->id, 'message' => $data['message']]);
}
public function myJoin(TcpConnection $connection, $event, $data)
{
$this->join($data['room'], $connection);
}
public function myRoomSeed(TcpConnection $connection, $event, $data)
{
$this->sendToRoom($data['room'], 'myRoomReceive', 'success', '成功', ['from' => $data['room'], 'message' => $data['message']]);
}
}
~~~
需要繼承`\addons\websocket\service\WebSocketManager`類。
后端代碼有改動,需重啟服務以后生效。
可調用方法:
~~~
/**
* 加入房間
* @param string|int|float $room
* @param TcpConnection|int $connection
* @return void
*/
public function join(string|int|float $room, TcpConnection|int $connection)
~~~
~~~
/**
* 離開房間
* @param string|int|float $room
* @param TcpConnection|int $connection
* @return void
*/
public function leave(string|int|float $room, TcpConnection|int $connection)
~~~
~~~
/**
* 給指定客戶端發送消息
* @param $connection 可以是具體連接對象,也可以是某個連接的id
* @param $event 事件名
* @param $status 狀態
* @param $message 消息
* @param $data 數據
* @return true
*/
public function send(TcpConnection|int $connection, string $event, $status = 'success', string $message = '', $data = null)
~~~
~~~
/**
* 向所有客戶端發送消息
* @param string $event
* @param $status 狀態
* @param string $message
* @param $data
* @return true
*/
public function sendAll(string $event, $status = 'success', string $message = '', $data = null)
~~~
~~~
/**
* 向所有客戶端發送事件,但不包括指定客戶端
* @param TcpConnection|int $connection
* @param string $event
* @param $status 狀態
* @param string $message
* @param $data
* @return true
*/
public function sendExceptSelf(TcpConnection|int $connection, string $event, $status = 'success', string $message = '', $data = null)
~~~
~~~
/**
* 向某個分組的所有客戶端發送事件
* @param string|int|float $room
* @param string $event
* @param $status 狀態
* @param string $message
* @param $data
* @return true
*/
public function sendToRoom(string|int|float $room, string $event, $status = 'success', string $message = '', $data = null)
~~~
~~~
/**
* 連接的時候
* @param $connection
* @return void
*/
public function onConnect(TcpConnection $connection)
~~~
~~~
/**
* 有消息的時候
* @param $connection
* @param $event
* @param $message
* @return void
*/
public function onMessage(TcpConnection $connection, $event, $message)
~~~
~~~
/**
* 有連接關閉的時候
* @param $connection
* @return void
*/
public function onClose(TcpConnection $connection)
~~~
## 客戶端
客戶端請自己發揮。
這里給了要給簡單的demo:http://www.域名.com/addons/websocket/index/index.html。
系統默認封裝了一個客戶端類:`public/static/addons/websocket/js/socket.js`
以下是使用該客戶端的demo:
~~~
var ws = new WebSocketClient({
worker : 'demo',// Worker名
url : '{$websocket_client}?login=2&id=5&a=aa&b=bb',
callback: {
// 錯誤事件
error: function (status, msg, data) {
console.log(status, msg)
},
// 統一事件
onopen: function () {
//console.log('onopen');
},
onclose: function () {
//console.log('onclose');
},
onmessage: function (message) {
//console.log(message)
},
// 自定義事件 參數:狀態 消息 數據
myConnect: function (status, message, data) {
console.log(status, message, data)
},
myReceive: function (status, message, data) {
console.log(status, message, data)
$('#messageBox').append('<p>來自'+ data.fromId + '發送的消息:'+ data.message +'</p>')
},
myRoomReceive: function (status, message, data) {
console.log(status, message, data)
$('#messageBox').append('<p>群里消息:'+ data.message +'</p>')
},
}
})
ws.createWebSocket();// 鏈接
$('#sendMsg').click(function () {
ws.send('mySend', {
clientId : $('#client_id').val(),
message : $('#message').val(),
})
})
$('#joinRoom').click(function () {
ws.send('myJoin', {
room : 'aaa'
})
})
$('#joinMsg').click(function () {
ws.send('myRoomSeed', {
room : 'aaa',
message : $('#message').val(),
})
})
~~~
ws.createWebSocket() :打開要給鏈接
ws.send('事件名', 消息數據):發送消息
## wss
~~~
var ws = new WebSocketClient({
worker : 'demo',// Worker名
url : wss://域名:100/wss?login=2&id=5&a=aa&b=bb',
...
~~~
nginx配置:
~~~
location /wss
{
proxy_pass http://127.0.0.1:8282;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
}
~~~