[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;
}
~~~