├── .gitignore ├── composer.json ├── config └── echo.php ├── readme.md └── src ├── BroadcastServerServiceProvider.php ├── Commands └── EchoCommand.php ├── EchoMessage.php ├── RedisOperation.php ├── Request.php ├── Server.php └── SocketServer.php /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zhaohehe/laravel-echo-server", 3 | "license": "MIT", 4 | "authors": [ 5 | { 6 | "name": "zhaohehe", 7 | "email": "zhaohehedola@gmail.com" 8 | } 9 | ], 10 | "autoload": { 11 | "psr-4": { 12 | "EchoServer\\": "src/" 13 | } 14 | }, 15 | "minimum-stability": "dev", 16 | "require": {} 17 | } 18 | -------------------------------------------------------------------------------- /config/echo.php: -------------------------------------------------------------------------------- 1 | '127.0.0.1', 12 | /* 13 | |-------------------------------------------------------------------------- 14 | | Socket server port 15 | |-------------------------------------------------------------------------- 16 | | 17 | | 18 | | 19 | */ 20 | 'port' => '3523', 21 | ]; -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## laravel-echo-server 2 | >这是一个用来支持laravel的事件广播的socket服务器 3 | 4 | ## 安装 5 | 首先,你必须为你的php安装swoole扩展以及redis扩展,推荐使用php7 6 | 7 | 直接用composer安装 8 | ``` 9 | composer require zhaohehe/laravel-echo-server 10 | ``` 11 | 然后在```app.php```中的providers数组中加入下面的一项 12 | ``` 13 | \EchoServer\BroadcastServerServiceProvider::class, 14 | ``` 15 | 最后运行下面的命令,发布配置文件 16 | ``` 17 | php artisan vendor:publish 18 | ``` 19 | 20 | ## 使用 21 | 开启socket服务器 22 | ``` 23 | php artisan echo start 24 | ``` 25 | 你可以在echo.php文件中配置服务器监听的端口,默认是:3523 26 | 27 | 你需要在.env中设置BROADCAST_DRIVER=redis 28 | 29 | 前端代码: 30 | ```html 31 | 32 | 33 | 34 | 35 | Title 36 | 37 | 38 |
39 | 40 | 41 | 66 | 67 | ``` 68 | 69 | 你的event必须实现ShouldBroadcast接口,那么,当你的事件被触发的时候,前端页面会获取到实时的message 70 | 71 | ## 最后 72 | 73 | 这是一个非常简陋的事件广播服务,只实现了最基本的功能,验证一下想法,我会去仔细研究下reids和laravel的广播以及swoole然后来完善它。 74 | -------------------------------------------------------------------------------- /src/BroadcastServerServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 22 | __DIR__ . '/../config/echo.php' => config_path('echo.php'), 23 | ]); 24 | } 25 | 26 | 27 | /** 28 | * Register services. 29 | * 30 | * @return void 31 | */ 32 | public function register() 33 | { 34 | $this->mergeConfigFrom( 35 | __DIR__ . '/../config/echo.php', 'echo' 36 | ); 37 | $this->commands([ 38 | Commands\EchoCommand::class, 39 | ]); 40 | } 41 | } -------------------------------------------------------------------------------- /src/Commands/EchoCommand.php: -------------------------------------------------------------------------------- 1 | argument('action'); 46 | 47 | switch ($action) { 48 | 49 | case 'start': 50 | $this->start(); 51 | break; 52 | } 53 | } 54 | 55 | 56 | public function start() 57 | { 58 | $serv = new Server(); 59 | } 60 | } -------------------------------------------------------------------------------- /src/EchoMessage.php: -------------------------------------------------------------------------------- 1 | request = new Request(); 19 | 20 | $redisOperate = new RedisOperation(); 21 | $this->redis = $redisOperate->getRedis(); 22 | 23 | } 24 | 25 | public function message($socketServer, $frame) 26 | { 27 | $fd = $frame->fd; 28 | $this->request->parse($frame->data); 29 | 30 | $event = $this->request->getEvent(); 31 | $channel = $this->request->getChannel(); 32 | 33 | $this->redis->subscribe([$channel], function ($instance, $channelName, $message) use ($socketServer, $fd, $event, $channel) { 34 | 35 | $message = json_decode($message); 36 | $eventName = $message->event; 37 | 38 | if ($eventName == $event && $channelName == $channel) { 39 | $socketServer->push($fd, json_encode($message->data)); 40 | } 41 | 42 | }); 43 | 44 | } 45 | } -------------------------------------------------------------------------------- /src/RedisOperation.php: -------------------------------------------------------------------------------- 1 | redis = new Redis(); 17 | 18 | $host = config('database.redis.default.host'); 19 | 20 | $port = config('database.redis.default.port'); 21 | 22 | $database = config('database.redis.default.database'); 23 | 24 | $this->redis->pconnect($host, $port, $database); 25 | 26 | } 27 | 28 | public function getRedis() 29 | { 30 | return $this->redis; 31 | } 32 | } -------------------------------------------------------------------------------- /src/Request.php: -------------------------------------------------------------------------------- 1 | data = json_decode($data); 29 | } 30 | 31 | public function getChannel() 32 | { 33 | try { 34 | $channel = $this->data->channel; 35 | return $channel; 36 | } catch (\Exception $e) { 37 | 38 | } 39 | } 40 | 41 | public function getEvent() 42 | { 43 | try { 44 | $event = $this->data->event; 45 | return $this->getEventNameSpace().$event; 46 | } catch (\Exception $e) { 47 | 48 | } 49 | } 50 | 51 | protected function getEventNameSpace() 52 | { 53 | try { 54 | return $this->data->namespace; 55 | } catch (\Exception $e) { 56 | 57 | } 58 | return $this->eventNameSpace; 59 | } 60 | } -------------------------------------------------------------------------------- /src/Server.php: -------------------------------------------------------------------------------- 1 | serv = new SocketServer(); 26 | 27 | $this->serv->start(); 28 | } 29 | } -------------------------------------------------------------------------------- /src/SocketServer.php: -------------------------------------------------------------------------------- 1 | socketServer = new swoole_websocket_server(config('echo.host'), config('echo.port')); 26 | 27 | $this->socketServer->set([ 28 | 'worker_num' => 8, 29 | 'daemonize' => false, 30 | ]); 31 | 32 | $this->echoMessage = new EchoMessage(); 33 | 34 | $this->socketServer->on('open', [$this, 'onOpen']); 35 | $this->socketServer->on('message', [$this->echoMessage, 'message']); 36 | $this->socketServer->on('close', [$this, 'onClose']); 37 | 38 | } 39 | 40 | 41 | public function start() 42 | { 43 | $this->socketServer->start(); 44 | } 45 | 46 | 47 | 48 | public function onOpen($socketServer, $request) 49 | { 50 | // $fd[] = $request->fd; 51 | // $fds[] = $fd; 52 | // $this->echoMessage->setFd($fds); 53 | } 54 | 55 | 56 | public function onClose($socketServer, $fd) 57 | { 58 | echo "client-{$fd} is closed\n"; 59 | } 60 | 61 | } --------------------------------------------------------------------------------