方案一 composer 安装配置安装 LaravelS 扩展包:
composer require hhxsv5/laravel-s
Laravel 5.5 以上版本可用,无需手动在 config/app.php
配置文件中注册,运行Artisan 命令相应脚本和配置文件发布到根目录下
php artisan laravels publish
该命令会发布配置文件 laravels.php
到 config
目录下,以及脚本文件到 bin
目录下
你可以在配置文件中对 Swoole 进行一些基本配置,而脚本文件主要用于管理 Swoole 服务的启动、重载、关闭等操作。
启动LaravelS
//命令启动 LaravelS
php bin/laravels start
这样,Swoole 服务就被启动起来,监听本地的 5200 端口,如果有请求发送到这个端口,它就可以进行处理。
此外 php bin/laravels
还支持其它命令对 LaravelS 进行管理:
方案二 pecl 命令安装需要先安装pecl
php swoole 扩展安装
pecl install swoole
修改 php.ini 配置文件
extension=swoole.so
重启 php-fpm 不同系统命令不同
sudo service php-fpm start # 启动php-fpm
查看 swoole 扩展装好了
php -m
安装 laraveltw/laravel-swoole
在项目根目录下使用 composer安装
composer require swooletw/laravel-swoole -vvv
最好加上 -vvv 参数,因为安装很慢,会给人一种没有安装被卡主的感觉。最好别再本地执行或者在 PHPstorm 中执行。因为 windows 不支持 laravel-swoole, 会有各种问题。可以在虚拟机的项目根目录下执行安装时需要耐心。当在 composer.josn 中看到下图标识的表示安装成功
Swoole安装好以后就是写服务器端的代码,可以自己写php文件websocket.php
代码如下:
<?php
ignore_user_abort(); // 后台运行
set_time_limit(0); // 取消脚本运行时间的超时上限
//创建一个websocket服务器
$ws_server = new swoole_websocket_server('0.0.0.0', 9501);
//创建一个用于存储的redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$ws_server->on('open', function ($ws, $request) use ($redis) {
$redis->sAdd('id', $request->fd);
$mes = '用户:'.$request->fd.'已加入聊天室';
$redis->sAdd('mes', $mes);
pushAll($redis,$ws,$mes);
getAllMes($redis,$ws);
});
$ws_server->on('message', function ($ws, $frame) use ($redis) {
$mes = '用户:'.$frame->fd.'<br/>'.$frame->data;
pushAll($redis,$ws,$mes);
});
//监听WebSocket连接关闭事件
$ws_server->on('close', function ($ws, $fd) use ($redis) {
$redis->srem('key:'.$id,$fd);
$mes = '用户:'.$fd.'已退出聊天室';
$redis->sAdd('mes', $mes);
pushAll($redis,$ws,$mes);
});
$ws_server->start();
/**
* 登录时获取以前的消息
*/
function getAllMes($redis,$ws){
$mesLists = $redis->sMembers('mes');
foreach ($mesLists as $mes){
pushAll($redis,$ws,$mes);
}
}
/**
* 给所有用户发信息
*/
function pushAll($redis,$ws,$mes){
$fds = $redis->sMembers('id');
foreach ($fds as $fd){
if($ws->exist($fd)){
$ws->push($fd,$mes);
}
}
}
然后linux运行
php webcoket.php
以上是一种方法,还可以写一个自动加载的方法例如
使用 laravel 自带的方法 artisan
php artisan make:command Swoole
会在 app\Console\Command\ 目录下生成 Swoole 文件
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use swoole_websocket_server;
class Swoole extends Command
{
protected $signature = 'swoole {action}';
protected $description = 'Command description';
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
* 这个方法中的逻辑需要自己写
* @return mixed
*/
public function handle()
{
$action = $this->argument('action');
switch ($action) { //方法可以自己写调用
case 'close':
break;
default:
$this->start();
break;
}
}
public function start()
{
// 这里是监听的服务端口号
$this->ws = new swoole_websocket_server("0.0.0.0", 9500);
//监听WebSocket连接打开事件
$this->ws->on('open', function ($ws, $request) {
$this->ws->push($request->fd, "is ok\n"); //链接服务器成功返回提示
});
//监听WebSocket消息事件
$this->ws->on('message', function ($ws, $frame) {
$this->info("client is SendMessage\n" . $frame);
});
//监听WebSocket主动推送消息事件
$this->ws->on('request', function ($request, $response) {
$scene = $request->post['scene'];
foreach ($this->ws->connections as $fd) {
if ($this->ws->isEstablished($fd)) {
$this->ws->push($fd, $scene);
}
}
});
//监听WebSocket连接关闭事件
$this->ws->on('close', function ($ws, $fd) {
$this->info("client is close\n");
});
$this->ws->start();
}
}
在 Kernel.php 文件中注册这个 Swoole 类
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
protected $commands = [
\App\Console\Commands\Swoole::class,
];
protected function schedule(Schedule $schedule)
{
}
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
在虚拟机的根目录下执行
php artisan swoole start
就会开启一个长起进程到这里服务器和后端代码完成现在需要一个前端页来实现长链接
前端代码很简单
<!doctype html>
<html>
<head>
<title>测试WebSocket</title>
</head>
<div id="WebSocket"></div>
<body>
<script>
var ws = new WebSocket("ws://ip:9500");
ws.onopen = function(event) {
console.log("客户端已连接上!");
ws.send("hello server,this is client!"); //客户端给服务端推送消息
};
ws.onmessage = function(event) {
var parent = document.getElementById('WebSocket');
var div = document.createElement("div");
div.innerHTML = event.data
parent.appendChild(div);
console.log("服务器传过来的数据是:" + event.data);
}
ws.onclose = function(event) {
console.log("连接已关闭");
};
</script>
</body>