Laravel8使用laravel-s实现WebSocket服务器

 4603

Laravel8使用laravel-s实现WebSocket服务器.通过 详解基于Laravel8下的LaravelS实现高性能HTTP服务器 我们安装了LaravelS并实现了一个HTTP服务器,那么本篇文章在此基础上在实现一个Websocket服务器。

创建WebSocketService类

创建WebSocketService类并实现Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface类。

文件位置:app/Services/WebSocketService.php

  1. <?php
  2.    
  3. namespace App\Services;
  4. use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;
  5. use Swoole\Http\Request;
  6. use Swoole\Http\Response;
  7. use Swoole\WebSocket\Frame;
  8. use Swoole\WebSocket\Server;
  9. use Illuminate\Support\Facades\Log;
  10. /**
  11. * @see https://wiki.swoole.com/#/start/start_ws_server
  12. */
  13. class WebSocketService implements WebSocketHandlerInterface
  14. {
  15.    // 声明没有参数的构造函数
  16.    public function __construct()
  17.    {
  18.    }
  19.    
  20.    public function onOpen(Server $server, Request $request)
  21.    {
  22.        // 在触发onOpen事件之前,建立WebSocket的HTTP请求已经经过了Laravel的路由,
  23.        // 所以Laravel的Request、Auth等信息是可读的,Session是可读写的,但仅限在onOpen事件中。
  24.        // \Log::info('New WebSocket connection', [$request->fd, request()->all(), session()->getId(), session('xxx'), session(['yyy' => time()])]);
  25.        // 此处抛出的异常会被上层捕获并记录到Swoole日志,开发者需要手动try/catch
  26.        Log::info('WebSocket 建立连接');
  27.        $server->push($request->fd, 'Welcome to LaravelS');
  28.    }
  29.    public function onMessage(Server $server, Frame $frame)
  30.    {
  31.        // \Log::info('Received message', [$frame->fd, $frame->data, $frame->opcode, $frame->finish]);
  32.        // 此处抛出的异常会被上层捕获并记录到Swoole日志,开发者需要手动try/catch
  33.        $server->push($frame->fd, date('Y-m-d H:i:s'));
  34.    }
  35.    public function onClose(Server $server, $fd, $reactorId)
  36.    {
  37.           Log::info('websocket 关闭');
  38.    }
  39. }

修改配置文件

文件位置:app/config/laravels.php

  1. 'websocket'      => [
  2.    'enable'  => true, // 注意:设置enable为true
  3.    'handler' => \App\Services\WebSocketService::class,
  4. ],
  5. 'swoole'         => [
  6.    //...
  7.    // dispatch_mode只能设置为2、4、5,https://wiki.swoole.com/#/server/setting?id=dispatch_mode
  8.    'dispatch_mode' => 2,
  9.    //...
  10. ],

修改nginx配置文件

文件位置:/usr/local/nginx/conf/vhosts/laravel_s.conf

  1. map $http_upgrade $connection_upgrade {
  2.    default upgrade;
  3.    ''      close;
  4. }
  5. upstream laravels {
  6.   # 此处注意,我使用的是Linux系统环境,因此这里使用的是Linux中的IP地址
  7.   # 由于默认是127.0.0.1,或是在Linux中可能会导致websocket无法完成服务
  8.   server 192.168.133.131:5200 weight=5 max_fails=3 fail_timeout=30s;
  9.   keepalive 16;
  10. }
  11. server {
  12.   listen 80;
  13.   server_name laravel-s.com;
  14.   root /www/laravel_swoole/public;
  15.   index index.php index.html index.htm;
  16.   location / {
  17.       try_files $uri @laravels;
  18.   }
  19.    # 配置websockeet
  20.    location = /ws {
  21.        proxy_http_version 1.1;
  22.        proxy_set_header X-Real-IP $remote_addr;
  23.        proxy_set_header X-Real-PORT $remote_port;
  24.        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  25.        proxy_set_header Host $http_host;
  26.        proxy_set_header Scheme $scheme;
  27.        proxy_set_header Server-Protocol $server_protocol;
  28.        proxy_set_header Server-Name $server_name;
  29.        proxy_set_header Server-Addr $server_addr;
  30.        proxy_set_header Server-Port $server_port;
  31.        proxy_set_header Upgrade $http_upgrade;
  32.        proxy_set_header Connection $connection_upgrade;
  33.        proxy_pass http://laravels;
  34.    }
  35. # 配置laravels
  36.    location @laravels {
  37.       proxy_http_version 1.1;
  38.       proxy_set_header Connection "";
  39.       proxy_set_header X-Real-IP $remote_addr;
  40.       proxy_set_header X-Real-PORT $remote_port;
  41.       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  42.       proxy_set_header Host $http_host;
  43.       proxy_set_header Scheme $scheme;
  44.       proxy_set_header Server-Protocol $server_protocol;
  45.       proxy_set_header Server-Name $server_name;
  46.       proxy_set_header Server-Addr $server_addr;
  47.       proxy_set_header Server-Port $server_port;
  48.       proxy_pass http://laravels;
  49.   }
  50. }

注意:laravels配置中的server需要填写本机IP。由于我使用的是Linux系统,因此配置了Linux系统中的IP。


配置.env文件

  1. LARAVELS_LISTEN_IP=192.168.133.131
  2. LARAVELS_DAEMONIZE=true

LARAVELS_LISTEN_IP要与upstream laravels配置的IP一样


启动laravels

切换到应用根目录,启动laravels

  1. php bin/laravels start

重启nginx服务器

  1. systemctl restart nginx.service


编写前端界面

testSwoole.html,此界面位于windows

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title></title>
  5. </head>
  6. <body>
  7. <input id="input" style="width: 100%;" >
  8. <script>
  9. window.onload = function() {
  10.     let nick = prompt('Enter your nickname');
  11.     let input = document.getElementById('input');
  12.     input.focus();
  13.     // 初始化客户端套接字并建立连接
  14.     let socket = new WebSocket("ws://laravel-s.com/ws");
  15.     // 建立连接时触发
  16.     socket.onopen = function(event) {
  17.         console.log('连接开始...');
  18.     }
  19.     // 接收到服务器信息
  20.     socket.onmessage = function(event) {
  21.         let msg = event.data;
  22.         let node = document.createTextNode(msg);
  23.         let div = document.createElement('div');
  24.         div.appendChild(node);
  25.         document.body.insertBefore(div,input);
  26.         input.scrollIntoView();
  27.     }
  28.     // 关闭连接时触发
  29.     socket.onclose = function(event) {
  30.         console.log('连接关闭...');
  31.     }
  32.     input.onchange = function() {
  33.         let msg = nick + ": " + input.value;
  34.         socket.send(msg);
  35.         input.value="";
  36.     }
  37. }
  38. </script>
  39. </body>
  40. </html>

尤其注意 let socket = new WebSocket("ws://laravel-s.com/ws"); 此时已经变成域名,默认80端口。当访问此页面并输入信息后,客户端发起协议升级请求后将信息发送到指定地址

打开该html页面并输入信息后查看websocket通信请求过程,可以看到协议已经升级为websocket

  1. # 通用头
  2. General
  3. Request URL: ws://laravel-s.com/ws
  4. Request Method: GET
  5. Status Code: 101 Switching Protocols
  6. # 响应头
  7. Connection: upgrade
  8. Date: Wed, 10 Mar 2021 16:39:21 GMT
  9. Sec-Websocket-Version: 13
  10. Upgrade: websocket
  11. # 通用头
  12. Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
  13. Sec-WebSocket-Key: LeAIasPj2v1aK4TKw0QqsA==
  14. Sec-WebSocket-Version: 13
  15. Upgrade: websocket

关于报错

刚编写完成并运行时,websocket客户端(也就是浏览器运行的testSwoole.html)出现failed: Error during WebSocket handshake: Unexpected response code: 404错误,这个错误如何解决?都知道404为页面错误,根据这个我仔细检查了代码,没有错误,下面来说说我的解决方法吧, 虽然有些不知所以然。

解决方法

1)重启 laravels

2)重启nginx

我就是这样解决了这个错误,如何你也遇到同样的问题,欢迎一起交流学习。


本文网址:https://www.zztuku.com/index.php/detail-13792.html
站长图库 - Laravel8使用laravel-s实现WebSocket服务器
申明:本文转载于《自如初博客》,如有侵犯,请 联系我们 删除。

评论(0)条

您还没有登录,请 登录 后发表评论!

提示:请勿发布广告垃圾评论,否则封号处理!!

    编辑推荐

    电子商务网站管理员后台UI