【旧文搬运】为你的 Laravel 应用添加一个基于 Swoole 的 WebSocket 服务

news2024/11/15 21:52:49

做了一个基于 Swoole 的 WebSocket 扩展包,可以用来做实时状态推送,或者自定义消息处理实现 im,有需要的可以看看: [giorgio-socket]

在这里插入图片描述

使用方法

安装

安装扩展包

composer require wu/giorgio-socket

发布配置文件

php artisan vendor:publish --provider="GiorgioSocket\Providers\SocketServiceProvider"

运行 Socket 服务

php artisan socket:start

注意事项

  • 可以通过实现 GiorgioSocket\Services\Handlers\Interfaces 下的接口类来自定义自己的业务逻辑。

  • 如果要从服务端发送消息,这里有两种方式:

    • 第一种,借助 Laravel HTTP 客户端
      Route::get('/socket', function () {
          \Illuminate\Support\Facades\Http::asForm()->post('http://127.0.0.1:9501', [
              'to' => 2,
              'message' => 'server message',
          ]);
      });
      
    • 第二种:借助 Laravel Listener,需要将 .env 文件中的 QUEUE_CONNECTION 配置修改为 redis 或其他异步队列。配置更改后,运行以下命令:php-artisan queue:work --queue=socket-listener监听队列,然后按以下代码调用 event
      Route::any('socket', function (Request $request){
          \GiorgioSocket\Events\SocketEvent::dispatch($request->get('to'), $request->get('message'));
      });
      
  • 如果你正在使用 laravel/breeze 扩展包,并且使用了 Blade 模板,可以将以下代码粘贴到 dashboard.blade.php 中进行快速测试:

      @auth
          <div class="py-12">
              <div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
                  <div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
                      <div class="grid grid-cols-1 md:grid-cols-2">
                          <div class="p-6" id="server-message">
                              messages:<br/>
                          </div>
    
                          <div class="p-6">
                              <label class="block font-medium text-sm text-gray-700 dark:text-gray-300" for="from">from</label>
                              <input class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm block mt-1 w-full" value="{{ auth()->user()->getKey() }}" id="from">
                              <label class="block font-medium text-sm text-gray-700 dark:text-gray-300" for="to">to</label>
                              <input class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm block mt-1 w-full" value="" id="to">
                              <label class="block font-medium text-sm text-gray-700 dark:text-gray-300" for="message">message</label>
                              <textarea class="border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm block mt-1 w-full" id="message"></textarea>
                              <input class="inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 mt-3" type="button" id="submit" value="submit">
                          </div>
                      </div>
                  </div>
              </div>
          </div>
          <script type="text/javascript">
            let heartBeatTimer = 0;
            let socket = connectWebSocket();
    
            function startHeartbeat(interval) {
              interval = interval || 30;
              heartBeatTimer = setInterval(function () {
                sendMessage(null, "heart_beat");
              }, interval * 1000);
            }
    
            function stopHeartbeat() {
              clearInterval(heartBeatTimer);
            }
    
            function connectWebSocket() {
              const wsServer = 'ws://127.0.0.1:9501';
              const socket = new WebSocket(wsServer);
    
              let userId = document.getElementById('from').value;
              socket.onopen = function (evt) {
                let data = {
                  user_id: userId,
                  type: 'connect'
                };
                console.log('open', data)
                socket.send(JSON.stringify(data));
              };
    
    
              socket.onmessage = function (evt) {
                console.log('get message from server: ' + evt.data);
    
                if (evt.data !== 'heart_beat') {
                  let data = JSON.parse(evt.data);
                  let message = document.getElementById("server-message")
                  message.innerHTML += data.user_name + ': ' + data.data + '<br/>'
                }
              };
    
              socket.onerror = function (evt) {
                console.log(evt);
              };
    
              socket.onclose = function () {
                let data = {
                  user_id: userId,
                  type: 'close'
                };
                socket.send(JSON.stringify(data));
              };
              return socket;
            }
    
            function sendMessage(to, message) {
              if (socket != null && socket.readyState === WebSocket.OPEN) {
                if (message !== 'heart_beat') {
                  let messageBox = document.getElementById("server-message")
                  messageBox.innerHTML += 'me: ' + message + '<br/>'
                }
                let from = document.getElementById("from")
                socket.send(JSON.stringify({
                  user_id: from.value,
                  user_name: '{{ auth()->user()->name }}',
                  to: to,
                  type: 'message',
                  data: message,
                }));
                console.log("webSocket send message:" + JSON.stringify({
                  user_id: from.value,
                  user_name: '{{ auth()->user()->name }}',
                  to: to,
                  type: 'message',
                  data: message,
                }));
              } else {
                console.log("webSocket closed");
              }
            }
    
            let button = document.getElementById("submit");
            button.addEventListener('click', function () {
              let message = document.getElementById("message");
              let to = document.getElementById("to");
              sendMessage(to.value, message.value)
            });
    
          </script>
      @endauth
    

    如有任何疑问,欢迎提交 [issue]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1486100.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

可莉炸鱼

情况有s*k>n&#xff0c;最多炸鱼数为n s*k<n&#xff0c;最多炸鱼数为s*k 将s*k转化为k个s相加&#xff0c;每次结果与n比较 #include<iostream> #include<vector> #include<algorithm> using namespace std; #define endl \n #define ll long lon…

Java---文件,流✨❤️

文章目录 1.遍历文件夹2.遍历子文件夹3.练习流4.以字节流的形式读取文件内容5.以字节流的形式向文件写入数据顶折纠问6 .写入数据到文件 1.遍历文件夹 一般说来操作系统都会安装在C盘&#xff0c;所以会有一个 C:\WINDOWS目录。 遍历这个目录下所有的文件(不用遍历子目录) 找出…

pyqt5怎么返回错误信息给页面(警告窗口)

在软件设计中&#xff0c;我们可能会遇到对异常的处理&#xff0c;有些异常是用户需要看到的&#xff0c;比如说&#xff0c;当我们登录出错的时候&#xff0c;后端需要给我们返回响应的错误信息&#xff0c;就像下图实现的这样。 类似这种效果&#xff0c;我们该如何实现&…

选择何种操作系统作为网站服务器

选择操作系统时&#xff0c;需考虑稳定性、安全性、成本、兼容性和技术支持等因素&#xff0c;常见选项有Windows Server和Linux发行版。 选择网站服务器的操作系统是一个关键的决策&#xff0c;因为它将影响到网站的性能、稳定性、安全性以及未来的扩展性&#xff0c;目前市场…

ES向量功能实战:向量搜索

1 缘起 项目需要&#xff0c;向量搜索使用ES&#xff0c;为了顺利使项目顺利交付&#xff0c;开始学习ES的稠密向量功能&#xff0c;本文即ES向量的实践&#xff1a;增删查改。ES从7.x版本支持向量功能&#xff0c;为测试ES向量功能&#xff0c;需要使用7.x及以上的版本。本文…

算法刷题day20:二分

目录 引言概念一、借教室二、分巧克力三、管道四、技能升级五、冶炼金属六、数的范围七、最佳牛围栏 引言 这几天一直在做二分的题&#xff0c;都是上了难度的题目&#xff0c;本来以为自己的二分水平已经非常熟悉了&#xff0c;没想到还是糊涂了一两天才重新想清楚&#xff0…

vue3 vite项目一运行就401(Unauthorized)

问题&#xff1a;项目一执行&#xff1a; pnpm run dev, 启动就出错&#xff0c; Failed to load resource: the server responded with a status of 401 (Unauthorized) 分析&#xff1a; 项目之前是正常运行的&#xff0c;没有问题&#xff0c;回溯刚刚改动&#xff0c;还原…

W5300驱动说明

W5300是一款带有硬件协议栈的网络芯片&#xff0c;内部拥有128K的缓存&#xff0c;最大支持8路socket通信&#xff0c;与MCU之间通过16位数据总线通信&#xff0c;通信速度远超W5500之类以SPI作为通信接口的网络芯片&#xff0c;特别适合对高速网络传输有需求的应用。 本次使用…

基于springboot+vue的疫苗发布和接种预约系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

关于工业 24V 电源转换电路参考设计

一. 概述 在工业邻域的应用中&#xff0c;部分电路板输入电源为 24V&#xff0c;而电路板上 MCU 及外设等的供电多为 3.3V、5V 以及 12V&#xff0c;因此设计将 24V 降压转换为各种电压非常有必要。常用的电源转换芯片有 DCDC 及 LDO 等&#xff0c;了解选型依据及其电路…

DolphinScheduler——调度系统数仓任务编排规范

原文大佬的这篇DS数仓任务编排规范有借鉴意义&#xff0c;这里摘抄下来用作学习和知识沉淀。 前言 在使用DolphinScheduler&#xff08;以下简称DS&#xff09;做数仓任务管理时&#xff0c;数据建模分层落地到调度上缺少规范&#xff0c;往往比较随意&#xff0c;例如将所有任…

OpenCV 4基础篇| OpenCV图像的裁切

目录 1. Numpy切片1.1 注意事项1.2 代码示例 2. cv2.selectROI()2.1 语法结构2.2 注意事项2.3 代码示例 3. Pillow.crop3.1 语法结构3.2 注意事项3.3 代码示例 4. 扩展示例&#xff1a;单张大图裁切成多张小图5. 总结 1. Numpy切片 语法结构&#xff1a; retval img[y:yh, x…

【JavaEE进阶】CSS选择器的常见用法

CSS选择器的主要功能就是选中页面指定的标签元素&#xff0c;选中了元素&#xff0c;才可以设置元素的属性。 CSS选择器主要有以下几种: 标签选择器类选择器id选择器复合选择器通配符选择器 接下来用代码来学习这几个选择器的使用。 <!DOCTYPE html> <html lang&q…

【C++】set、multiset与map、multimap的使用

目录 一、关联式容器二、键值对三、树形结构的关联式容器3.1 set3.1.1 模板参数列表3.1.2 构造3.1.3 迭代器3.1.4 容量3.1.5 修改操作 3.2 multiset3.3 map3.3.1 模板参数列表3.3.2 构造3.3.3 迭代器3.3.4 容量3.3.5 修改操作3.3.6 operator[] 3.4 multimap 一、关联式容器 谈…

Angular基础---HelloWorld---Day1

文章目录 1. 创建Angular 项目2.对Angular架构的最基本了解3.创建并引用新的组件&#xff08;component&#xff09;4.对Angular架构新的认识&#xff08;多组件&#xff09;5.组件中业务逻辑文件的编辑&#xff08;ts文件&#xff09;6.标签中属性的绑定(1) ID的绑定(2) class…

django项目 法律法规管理系统

1.项目结构 2.项目需求 1.用户管理模块 2.数据采集模块 3.知识管理模块 4.智能匹配模块 5.个人收藏模块 6.数据分析模块 7.页面展示模块 3.知识点 1.智能匹配模块推荐算法的实现原理 TF (Term Frequency)&#xff1a;词频&#xff0c;表示一个词在文档中出现的频…

Latex常用符号和技巧

Latex常用符号和技巧 随笔记录,不分顺序 一些有用的Latex资源 https://latexstudio.net/ https://www.latexstudio.net/articles/ IEEE相关文件(包括IEEETransaction Latex模板,参考文件模板,相关文件和个人搜集的Latex说明文件等) 链接:https://pan.baidu.com/s/1NJ…

每个大模型开发者都应该知道的数字

GitHub - ray-project/llm-numbers: Numbers every LLM developer should know 谷歌内部流传了一份由传奇工程师 Jeff Dean 整理的文档&#xff0c;名为《每个工程师都应该知道的数字》。大语言模型&#xff08;LLM&#xff09;开发人员们同样需要一组类似的数字为粗略计算做参…

steam++加速问题:出现显示443端口被 vmware-hostd(9860)占用的错误。

目录 前言&#xff1a; 正文&#xff1a; 前言&#xff1a; 使用Steam对GitHub进行加速处理时&#xff0c;建议使用2.8.6版本。 下载地址如下&#xff1a;Release 2.8.6 BeyondDimension/SteamTools GitHub 下载时注意自己的系统位数 正文&#xff1a; 使用GitHub时会使…

Spring重点记录

文章目录 1.Spring的组成2.Spring优点3.IOC理论推导4.IOC本质5.IOC实现&#xff1a;xml或者注解或者自动装配&#xff08;零配置&#xff09;。6.hellospring6.1beans.xml的结构为&#xff1a;6.2.Spring容器6.3对象的创建和控制反转 7.IOC创建对象方式7.1以有参构造的方式创建…