Laravel 5.2 使用 swoole websocket ,事件广播不成功? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
anai1943
V2EX    PHP

Laravel 5.2 使用 swoole websocket ,事件广播不成功?

  •  
  •   anai1943 2017 年 5 月 24 日 5070 次点击
    这是一个创建于 3256 天前的主题,其中的信息可能已经有所发展或是发生改变。

    app/Console/Commands/Swoole.php

    <?php namespace App\Console\Commands; use App\Handlers\SwooleHandler; use Illuminate\Console\Command; class Swoole extends Commad { /** * The name and signature of the console command. * * @var string */ protected $signature = 'swoole {action}'; /** * The console command description. * * @var string */ protected $description = 'swoole socket'; protected $ws; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { $action = $this->argument('action'); $this->ws = new \swoole_websocket_server( "http://" .env('SOCKET_DOMAIN'), env('SOCKET_PORT') ); $this->ws->set(['worker_num' => env('SOCKET_WORKER_NUM')]); switch ($action) { case 'start': $handler = new SwooleHandler(); $this->ws->on('Open', [$handler, 'onOpen']); $this->ws->on('Message', [$handler, 'onMessage']); $this->ws->on('Close', [$handler, 'onClose']); $this->ws->start(); break; case 'reload': $this->ws->reload(); break; case 'stop': $this->ws->stop(); break; } } } 

    app/Handlers/SwooleHandler.php

    <?php namespace App\Handlers; use LRedis; use App\Models\Message; class SwooleHandler { public function onOpen($ws, $request) { $user_id = $request->get['user_id']; echo "client - {$user_id} is opened\n"; LRedis::hSet('FRONT_USERS', $user_id, $request->fd); } public function onMessage($ws, $frame) { $user_id = $frame->data; $fd = LRedis::hGet('FRONT_USERS', $user_id); echo "client - {$fd} is send\n"; $num = Message::query()->where('user_id',$user_id)->count(); $ws->push($fd, $num); } public function onClose($ws, $fd) { echo "client - {$fd} is closed\n"; $all = LRedis::hGetAll('FRONT_USERS'); foreach ($all as $key => $val) { if ($fd == LRedis::hGet('FRONT_USERS', $key)) { LRedis::hDel('FRONT_USERS', $key); echo "del {$key}\n"; } } } } 

    app/Events/MessageEvent.php

    <?php namespace App\Events; use App\Models\Message; use App\Events\Event; use Illuminate\Queue\SerializesModels; use Illuminate\Contracts\Broadcasting\ShouldBroadcast; class MessageEvent extends Event implements ShouldBroadcast { use SerializesModels; public $user_id; /** * Create a new event instance. * * @return void */ public function __construct($from_user_id, $user_id, $content) { $this->model = new Message(); $this->from_user_id = $from_user_id; $this->user_id = $user_id; $this->cOntent= $content; } /** * Get the channels the event should be broadcast on. * * @return array */ public function broadcastOn() { return ['message-channel']; } } 

    app/Listeners/MessageListener.php

    <?php namespace App\Listeners; use App\Events\MessageEvent; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; class MessageListener { /** * Create the event listener. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param MessageEvent $event * @return void */ public function handle(MessageEvent $event) { $model = $event->model; $model->from_user_id = $event->from_user_id; $model->user_id = $event->user_id; $model->cOntent= $event->content; $model->save(); } } 

    app/Providers/EventServiceProvider.php

    <?php namespace App\Providers; use Illuminate\Contracts\Events\Dispatcher as DispatcherContract; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * 事件侦听器映射到应用程序 * * @var array */ protected $listen = [ // 站内信事件监听 'App\Events\MessageEvent' => [ 'App\Listeners\MessageListener', ], ]; /** * Register any other events for your application. * * @param \Illuminate\Contracts\Events\Dispatcher $events * @return void */ public function boot(DispatcherContract $events) { parent::boot($events); } } 

    前台模板

    <!doctype html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" cOntent="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <meta http-equiv="X-UA-Compatible" cOntent="ie=edge"> <title>OA 首页</title> </head> <body> <div style="width: 300px;margin: 100px auto;"> <h1>Hi, {{auth('front')->user()->name}}</h1> <a href="{{url('auth/logout')}}">Logout</a> </div> <script type="text/Javascript"> var exampleSocket = new WebSocket("ws://{{env('SOCKET_DOMAIN')}}:{{env('SOCKET_PORT')}}?user_id={{auth('front')->user()->id}}"); exampleSocket.Onopen= function (event) { exampleSocket.send({{auth('front')->user()->id}}); }; exampleSocket.Onmessage= function (event) { console.log(event.data); } </script> </body> </html> 

    运行 php artisan swoole start,前台页面第一次加载的时候,websocket 链接的 onopen, onmessage, onclose 都是可以正常运行的。

    Mac-Pro:xxx.com xxx$ php artisan swoole start client - 22 is opened client - 1 is send client - 1 is closed 

    但是执行 \Illuminate\Support\Facades\Event::fire(new \App\Events\MessageEvent($from_user_id, $user_id, $content)) 触发事件的时候,前台页面 onmessage 里面不能输出最新的数据。。求大神指教。谢谢!

    3 条回复    2017-05-26 08:54:08 +08:00
    torbrowserbridge
        1
    torbrowserbridge  
       2017 年 5 月 25 日
    0. MessageListener::handle() 的作用是什么?执行了吗?

    1. 广播驱动器是 Redis 吗?没看到在哪里订阅 channel 的呢?

    2. 广播执行了吗?你可能需要 listen queue 来执行队列任务。
    anai1943
        2
    anai1943  
    OP
       2017 年 5 月 25 日
    @torbrowserbridge
    0. MessageListener::handle() 执行了,是将 message 数据写入数据库
    1. 广播驱动是 redis,订阅 channel 不明白怎么写。。
    2. 运行 php artisan queue:listen 显示 Processed: Illuminate\Broadcasting\BroadcastEvent
    torbrowserbridge
        3
    torbrowserbridge  
       2017 年 5 月 26 日
    1. 写入数据库的目的是?为了统计 count ?
    2. 你这段没实现订阅。
    3. “运行 php artisan queue:listen 显示 Processed: Illuminate\Broadcasting\BroadcastEvent ” 这里证明 event 被广播出去了。
    4. 可以在 redis 命令行中输入:psubscribe * 来实现订阅全部 channel。看看当事件被广播后,终端是否有对应的输出。
    5. 如果 4 正常输出,尝试在 swoole 中实现 redis 订阅,然后将相应的结果写回对应的 fd
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     913 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 21:51 PVG 05:51 LAX 14:51 JFK 17:51
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86