联系邮箱:254200493@qq.com 登录 注册

Laravel+socket.io实现websocket

2020-01-11 17:07:48

websocket 相信很多人都知道,但是由于目前参与的公司项目用的不多,所以也就落下了。现在来补补课,本文主要是基于Laravel的事件广播、redis的订阅功能、nodejs/socket.io实现websocket的。

1、给Laravel安装predis;
composer require pusher/pusher-php-server(由于此次使用的是redis,可以不安装)
composer require predis/predis 

2、查看config/database.php:

'redis' => [

'cluster' => false,

'default' => [
'host' => env('REDIS_HOST', 'localhost'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => 0,
],

]

我们需要将redis的相关参数写到.env文件

3、新建事件及监听器
事件代码如下(记得要实现ShouldBroadcast接口哦):

<?php
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class WechatLoginedEvent extends Event implements ShouldBroadcast
{
use SerializesModels;

public $token;
protected $channel;

/**
* Create a new event instance.
*
* @param string $token
* @param string $channel
* @return void
*/
public function __construct($token, $channel)
{
$this->token = $token;
$this->channel = $channel;
}

/**
* Get the channels the event should be broadcast on.
*
* @return array
*/
public function broadcastOn()
{
return [$this->channel];
}

/**
* Get the name the event should be broadcast on.
*
* @return string
*/
public function broadcastAs()
{
return 'wechat.login';
}

/* public function onQueue()
{
return 'wechat_login_broadcast';
} */
}

监听器代码如下(这里实现了ShouldQueue,意味着将会使用到Laravel的队列):

<?php

namespace App\Listeners;

use Illuminate\Http\Request;
use Auth;
use App\Events\WechatLoginedEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class WechatLoginEventListener implements ShouldQueue
{
use InteractsWithQueue;
protected $request;
/**
* Create the event listener.
*
* @return void
*/
public function __construct(Request $request)
{
$this->request = $request;
}

/**
* 创建日记
* @param $event
*/
public function login($event){
info("event -------- ".$event->token);
//return false;
}

/**
* Handle the event.
*
* @param $event
* @return void
*/
public function subscribe($events)
{
$events->listen(
WechatLoginedEvent::class,
'App\Listeners\WechatLoginEventListener@login'
);
}
}

创建好事件及监听器之后,我们需要将EventServiceProvider注册事件订阅者:

protected $subscribe = [
//事件订阅者
WechatLoginEventListener::class,
];

4、查看config/broadcasting.php:

'default' => env('BROADCAST_DRIVER', 'pusher'),
默认的事件广播驱动是pusher,所以我们需要在.env文件增加BROADCAST_DRIVER=redis。至此,Laravel部分已经准备完毕,当然我们也可以先使用log的方式,然后执行看是否可以成功以确保前面的内容没有问题;

5、新建node项目

// server.js
var app = require('http').createServer(handler);
var io = require('socket.io')(app);

var Redis = require('ioredis');
var redis = new Redis({
port: 6379, // Redis port
host: '127.0.0.1', // Redis host
password:null,
db: 0,
});

app.listen(6001, function () {
console.log('Server is running!') ;
});

function handler(req, res) {
res.writeHead(200);
res.end('');
}

io.on('connection', function (socket) {
socket.on('message', function (message) {
console.log(message)
})
socket.on('disconnect', function () {
console.log('user disconnect')
})
});

redis.psubscribe('*', function (err, count) {});

redis.on('pmessage', function (subscrbed, channel, message) {
console.log("redis msg");
console.log(message);
message = JSON.parse(message);
console.log(channel);
var obj = {
channel : channel,
message:message
};
io.emit("message",JSON.stringify(obj));
});

执行该服务:node server.js

6、页面端主要代码如下:

<script type="text/javascript" src="/js/socket.io.js"></script>
<script type="text/javascript">
$(function(){
var socket = io.connect('ws://localhost:6001');
socket.on('message', function (data) {
console.log("server:"+data);
alert("收到通知");
});
});
</script>

7、由于我们实现ShouldQueue,所以还需要监听queue队列
php artisan queue:listen

接下来就看执行效果了,在需要执行的地方插入代码:event(new WechatLoginedEvent("content", "channel_1"));

这里有一个很酷炫的方式:php artisan tinker 进入tinker,接着执行event(new App\Events\WechatLoginedEvent("content", "channel_1"));



相关文章