1.安装swoole扩展
# 下载压缩包。可以到https://github.com/swoole/swoole-src/releases选择版本,本次示例采用swoole-4.8.13
wget https://github.com/swoole/swoole-src/archive/refs/tags/v4.8.13.tar.gz
tar -zxvf v4.8.13.tar.gz
cd v4.8.13
# (视自己PHP目录而定)
/usr/bin/phpize
./configure --with-php-config=/usr/bin/php-config
make && make install
此时扩展目录下可以看到swoole.so。
进入php.ini,新增
extension=swoole.so
高版本的PHP扩展会单独存放,通常在php.d,进入该文件夹新增扩展。
# 视自己目录而定
cd /etc/php.d/
vim 20-swoole.ini
# 写入一行
extension=swoole.so
重启php-fpm,执行php -m,可以看到里面已经有swoole。
2.简单socket使用
进入laravel项目根目录,随便创建一个文件
php artisan make:command SwooleSocket
主要代码如下:
public function start()
{
// 创建websocket服务器对象,监听127.0.0.1:9502端口
$this->ws = new \swoole_websocket_server("0.0.0.0", 9502);
// 监听WebSocket连接打开事件
$this->ws->on('open', function ($ws, $request) {
file_put_contents('/tmp/swoole'.date('Ymd').'.log',date('Y-m-d H:i:s').' [line: ' . __LINE__ . '] ' . basename(__FILE__) . ' | connect success '.print_r($request->fd,true).PHP_EOL,FILE_APPEND);
// 连接成功和对方打招呼
$ws->push($request->fd, "hello, welcome\n");
});
// 监听WebSocket消息事件
$this->ws->on('message', function ($ws, $frame) {
file_put_contents('/tmp/swoole'.date('Ymd').'.log',date('Y-m-d H:i:s').' [line: ' . __LINE__ . '] ' . basename(__FILE__) . ' | frame '.print_r($frame,true).PHP_EOL,FILE_APPEND);
$send = json_decode($frame->data, true);
if (!empty($send)) {
// 业务 TODO
}
// 接收成功
$ws->push($frame->fd, "server: success");
});
// 接收http请求获取参数
$this->ws->on('request', function ($request, $response) {
// 目前连接着的uid
$clients = $this->ws->getClientList();
foreach ($clients as $key => $value) {
$now_uids[] = $value;
}
file_put_contents('/tmp/swoole'.date('Ymd').'.log',date('Y-m-d H:i:s').' [line: ' . __LINE__ . '] ' . basename(__FILE__) . ' | now_uids '.print_r($now_uids,true).PHP_EOL,FILE_APPEND);
// 业务 TODO
});
// 监听WebSocket连接关闭事件
$this->ws->on('close', function ($ws, $fd) {
file_put_contents('/tmp/swoole'.date('Ymd').'.log',date('Y-m-d H:i:s').' [line: ' . __LINE__ . '] ' . basename(__FILE__) . ' | client closed '.print_r($fd,true).PHP_EOL,FILE_APPEND);
});
$this->ws->start();
}
运行
php artisan SwooleSocket
再写前端与他相连,主要代码如下:
<!DOCTYPE html>
<html>
<head>
<script src="../asset/jquery-3.3.1.js"></script>
<script src="../asset/jquery-3.3.1.min.js"></script>
<title>sw</title>
</head>
<body>
<div id="send">
发送
</div>
</body>
</html>
<script type="text/javascript">
var address = 'ws://服务器ip:9502';
if ("WebSocket" in window) {
console.log("您的浏览器支持websocket\n");
var ws = new WebSocket(address);
ws.onopen = function(){
var send_data = {'type': 'connect', 'myName': 'test'};
var send_srt = JSON.stringify(send_data);
ws.send(send_srt);
console.log("数据发送中");
}
ws.onmessage = function(evt){
var recv_msg = evt.data;
console.log("接受到的数据为:"+recv_msg);
}
ws.onerror = function(evt,e){
console.log("错误信息为"+e);
}
ws.onclose = function(){
console.log("连接已关闭");
}
} else {
console.log("您的浏览器不支持websocket\n");
}
// 发送内容
$("#send").on('click', function(){
var send_data = {'type': 'connect', 'myName': 'test', 'info': 'send!'};
var send_srt = JSON.stringify(send_data);
ws.send(send_srt);
});
</script>
可以看到日志和前端的打印都会收到彼此的消息