mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-17 20:54:52 +08:00
126 lines
55 KiB
HTML
126 lines
55 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-US">
|
||
<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">
|
||
<title>接入其他 WebSocket 客户端 | 炸毛框架 v3</title>
|
||
<meta name="description" content="">
|
||
<meta name="generator" content="VuePress 1.9.10">
|
||
<link rel="icon" href="/logo_trans.png">
|
||
<script>
|
||
var _hmt = _hmt || [];
|
||
(function () {
|
||
var hm = document.createElement("script");
|
||
hm.src = "https://hm.baidu.com/hm.js?f0f276cefa10aa31a20ae3815a50b795";
|
||
var s = document.getElementsByTagName("script")[0];
|
||
s.parentNode.insertBefore(hm, s);
|
||
})();
|
||
</script>
|
||
<meta name="description" content="一个高性能聊天机器人 + Web 框架">
|
||
<link rel="preload" href="/assets/css/0.styles.de075592.css" as="style"><link rel="preload" href="/assets/js/app.cf958133.js" as="script"><link rel="preload" href="/assets/js/2.4c04991c.js" as="script"><link rel="preload" href="/assets/js/1.d8755a39.js" as="script"><link rel="preload" href="/assets/js/38.75fa7a1c.js" as="script"><link rel="prefetch" href="/assets/js/10.960912c3.js"><link rel="prefetch" href="/assets/js/11.cd171694.js"><link rel="prefetch" href="/assets/js/12.ff9ca1d1.js"><link rel="prefetch" href="/assets/js/13.a56deac8.js"><link rel="prefetch" href="/assets/js/14.b222a011.js"><link rel="prefetch" href="/assets/js/15.31489867.js"><link rel="prefetch" href="/assets/js/16.e921dbc4.js"><link rel="prefetch" href="/assets/js/17.58f730d3.js"><link rel="prefetch" href="/assets/js/18.26c46c49.js"><link rel="prefetch" href="/assets/js/19.ee0bfd3b.js"><link rel="prefetch" href="/assets/js/20.bb3578b8.js"><link rel="prefetch" href="/assets/js/21.e66f7fe5.js"><link rel="prefetch" href="/assets/js/22.cba8ca48.js"><link rel="prefetch" href="/assets/js/23.cb49f41c.js"><link rel="prefetch" href="/assets/js/24.d95b175a.js"><link rel="prefetch" href="/assets/js/25.b0d69869.js"><link rel="prefetch" href="/assets/js/26.8e7089c0.js"><link rel="prefetch" href="/assets/js/27.333a53a1.js"><link rel="prefetch" href="/assets/js/28.df4b871c.js"><link rel="prefetch" href="/assets/js/29.5427ad45.js"><link rel="prefetch" href="/assets/js/3.07fc018e.js"><link rel="prefetch" href="/assets/js/30.7cb7445a.js"><link rel="prefetch" href="/assets/js/31.5c4bb546.js"><link rel="prefetch" href="/assets/js/32.7fc05474.js"><link rel="prefetch" href="/assets/js/33.9684a4f8.js"><link rel="prefetch" href="/assets/js/34.83e32a28.js"><link rel="prefetch" href="/assets/js/35.95d03df6.js"><link rel="prefetch" href="/assets/js/36.80aace42.js"><link rel="prefetch" href="/assets/js/37.1eaed2ee.js"><link rel="prefetch" href="/assets/js/39.117f5802.js"><link rel="prefetch" href="/assets/js/4.6623271b.js"><link rel="prefetch" href="/assets/js/40.57eba153.js"><link rel="prefetch" href="/assets/js/41.89c4a7c8.js"><link rel="prefetch" href="/assets/js/42.d8f92f99.js"><link rel="prefetch" href="/assets/js/43.5ee83631.js"><link rel="prefetch" href="/assets/js/44.c09b5b0c.js"><link rel="prefetch" href="/assets/js/45.bd850606.js"><link rel="prefetch" href="/assets/js/46.732b1cef.js"><link rel="prefetch" href="/assets/js/47.2a872d0d.js"><link rel="prefetch" href="/assets/js/48.959e18f4.js"><link rel="prefetch" href="/assets/js/49.a9bb32f7.js"><link rel="prefetch" href="/assets/js/5.073233e8.js"><link rel="prefetch" href="/assets/js/50.ca90a854.js"><link rel="prefetch" href="/assets/js/51.79142530.js"><link rel="prefetch" href="/assets/js/52.fe63ad16.js"><link rel="prefetch" href="/assets/js/53.ed84845a.js"><link rel="prefetch" href="/assets/js/54.3ab7e492.js"><link rel="prefetch" href="/assets/js/55.9028e407.js"><link rel="prefetch" href="/assets/js/56.8173f798.js"><link rel="prefetch" href="/assets/js/57.2166b068.js"><link rel="prefetch" href="/assets/js/58.7c52b6bf.js"><link rel="prefetch" href="/assets/js/59.e9965a7b.js"><link rel="prefetch" href="/assets/js/60.f277436c.js"><link rel="prefetch" href="/assets/js/61.3712f8fe.js"><link rel="prefetch" href="/assets/js/8.899a0731.js"><link rel="prefetch" href="/assets/js/9.e2e8da12.js"><link rel="prefetch" href="/assets/js/vendors~docsearch.303532f0.js">
|
||
<link rel="stylesheet" href="/assets/css/0.styles.de075592.css">
|
||
</head>
|
||
<body>
|
||
<div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="ant-row"><div class="nav-button"><i aria-label="icon: bars" class="anticon anticon-bars"><svg viewBox="0 0 1024 1024" focusable="false" data-icon="bars" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M912 192H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 284H328c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM104 228a56 56 0 1 0 112 0 56 56 0 1 0-112 0zm0 284a56 56 0 1 0 112 0 56 56 0 1 0-112 0zm0 284a56 56 0 1 0 112 0 56 56 0 1 0-112 0z"></path></svg></i> <span></span></div> <div class="ant-col ant-col-xs-24 ant-col-sm-24 ant-col-md-6 ant-col-lg-6 ant-col-xl-5 ant-col-xxl-4"><a href="/" class="router-link-active home-link"><img src="/logo_trans.png" alt="炸毛框架 v3" class="logo"> <span class="site-name">炸毛框架 v3</span></a> <div class="search-box mobile-search"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div></div> <div class="nav-space-between ant-col ant-col-xs-0 ant-col-sm-0 ant-col-md-18 ant-col-lg-18 ant-col-xl-19 ant-col-xxl-20"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><ul role="menu" id="nav" class="ant-menu ant-menu-horizontal ant-menu-root ant-menu-light"><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="/guide/">
|
||
指南
|
||
</a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="/event/">
|
||
事件
|
||
</a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="/components/bot/bot-context.html">
|
||
组件
|
||
</a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="/plugins/management.html">
|
||
插件
|
||
</a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="/advanced/">
|
||
进阶
|
||
</a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="/update/v3.html">
|
||
更新日志
|
||
</a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="/doxy/" target="_blank">
|
||
API 文档
|
||
<i aria-label="icon: link" class="anticon anticon-link"><svg viewBox="64 64 896 896" focusable="false" data-icon="link" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M574 665.4a8.03 8.03 0 0 0-11.3 0L446.5 781.6c-53.8 53.8-144.6 59.5-204 0-59.5-59.5-53.8-150.2 0-204l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3l-39.8-39.8a8.03 8.03 0 0 0-11.3 0L191.4 526.5c-84.6 84.6-84.6 221.5 0 306s221.5 84.6 306 0l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3L574 665.4zm258.6-474c-84.6-84.6-221.5-84.6-306 0L410.3 307.6a8.03 8.03 0 0 0 0 11.3l39.7 39.7c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c53.8-53.8 144.6-59.5 204 0 59.5 59.5 53.8 150.2 0 204L665.3 562.6a8.03 8.03 0 0 0 0 11.3l39.8 39.8c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c84.5-84.6 84.5-221.5 0-306.1zM610.1 372.3a8.03 8.03 0 0 0-11.3 0L372.3 598.7a8.03 8.03 0 0 0 0 11.3l39.6 39.6c3.1 3.1 8.2 3.1 11.3 0l226.4-226.4c3.1-3.1 3.1-8.2 0-11.3l-39.5-39.6z"></path></svg></i></a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="display:none;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li><li role="menuitem" class="ant-menu-item"><a href="https://docs-v2.zhamao.xin/" target="_blank">
|
||
炸毛框架 v2
|
||
<i aria-label="icon: link" class="anticon anticon-link"><svg viewBox="64 64 896 896" focusable="false" data-icon="link" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M574 665.4a8.03 8.03 0 0 0-11.3 0L446.5 781.6c-53.8 53.8-144.6 59.5-204 0-59.5-59.5-53.8-150.2 0-204l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3l-39.8-39.8a8.03 8.03 0 0 0-11.3 0L191.4 526.5c-84.6 84.6-84.6 221.5 0 306s221.5 84.6 306 0l116.2-116.2c3.1-3.1 3.1-8.2 0-11.3L574 665.4zm258.6-474c-84.6-84.6-221.5-84.6-306 0L410.3 307.6a8.03 8.03 0 0 0 0 11.3l39.7 39.7c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c53.8-53.8 144.6-59.5 204 0 59.5 59.5 53.8 150.2 0 204L665.3 562.6a8.03 8.03 0 0 0 0 11.3l39.8 39.8c3.1 3.1 8.2 3.1 11.3 0l116.2-116.2c84.5-84.6 84.5-221.5 0-306.1zM610.1 372.3a8.03 8.03 0 0 0-11.3 0L372.3 598.7a8.03 8.03 0 0 0 0 11.3l39.6 39.6c3.1 3.1 8.2 3.1 11.3 0l226.4-226.4c3.1-3.1 3.1-8.2 0-11.3l-39.5-39.6z"></path></svg></i></a></li><li role="menuitem" class="ant-menu-submenu ant-menu-submenu-horizontal ant-menu-overflowed-submenu" style="visibility:hidden;position:absolute;"><div aria-haspopup="true" class="ant-menu-submenu-title"><span>···</span><i class="ant-menu-submenu-arrow"></i></div></li></ul> <ul class="extra-group"><li><a href="https://github.com/zhamao-robot/zhamao-framework" target="_blank" rel="noopener noreferrer" class="repo-link"><i aria-label="icon: github" class="anticon anticon-github"><svg viewBox="64 64 896 896" focusable="false" data-icon="github" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M511.6 76.3C264.3 76.2 64 276.4 64 523.5 64 718.9 189.3 885 363.8 946c23.5 5.9 19.9-10.8 19.9-22.2v-77.5c-135.7 15.9-141.2-73.9-150.3-88.9C215 726 171.5 718 184.5 703c30.9-15.9 62.4 4 98.9 57.9 26.4 39.1 77.9 32.5 104 26 5.7-23.5 17.9-44.5 34.7-60.8-140.6-25.2-199.2-111-199.2-213 0-49.5 16.3-95 48.3-131.7-20.4-60.5 1.9-112.3 4.9-120 58.1-5.2 118.5 41.6 123.2 45.3 33-8.9 70.7-13.6 112.9-13.6 42.4 0 80.2 4.9 113.5 13.9 11.3-8.6 67.3-48.8 121.3-43.9 2.9 7.7 24.7 58.3 5.5 118 32.4 36.8 48.9 82.7 48.9 132.3 0 102.2-59 188.1-200 212.9a127.5 127.5 0 0 1 38.1 91v112.5c.8 9 0 17.9 15 17.9 177.1-59.7 304.6-227 304.6-424.1 0-247.2-200.4-447.3-447.5-447.3z"></path></svg></i></a></li> <!----></ul></nav></div></div> <!----></header> <aside class="sidebar"><!----> <ul class="sidebar-links"><li><a href="/components/" aria-current="page" title="组件" class="sidebar-link">组件</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>机器人组件</span> <span class="arrow right"><i aria-label="icon: down" class="anticon anticon-down"><svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>HTTP 组件</span> <span class="arrow down"><i aria-label="icon: down" class="anticon anticon-down"><svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/components/http/zmrequest.html" title="ZMRequest HTTP 客户端" class="sidebar-link">ZMRequest HTTP 客户端</a></li><li><a href="/components/http/websocket-access.html" aria-current="page" title="接入其他 WebSocket 客户端" class="active sidebar-link">接入其他 WebSocket 客户端</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/components/http/websocket-access.html#接入" title="接入" class="sidebar-link">接入</a></li><li class="sidebar-sub-header"><a href="/components/http/websocket-access.html#接收和发送" title="接收和发送" class="sidebar-link">接收和发送</a></li><li class="sidebar-sub-header"><a href="/components/http/websocket-access.html#连接断开事件" title="连接断开事件" class="sidebar-link">连接断开事件</a></li><li class="sidebar-sub-header"><a href="/components/http/websocket-access.html#消息帧" title="消息帧" class="sidebar-link">消息帧</a></li><li class="sidebar-sub-header"><a href="/components/http/websocket-access.html#事件外主动发送消息帧" title="事件外主动发送消息帧" class="sidebar-link">事件外主动发送消息帧</a></li><li class="sidebar-sub-header"><a href="/components/http/websocket-access.html#多服务器端口" title="多服务器端口" class="sidebar-link">多服务器端口</a></li></ul></li><li><a href="/components/http/websocket-client.html" title="框架内置 WebSocket 客户端" class="sidebar-link">框架内置 WebSocket 客户端</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>框架通用组件</span> <span class="arrow right"><i aria-label="icon: down" class="anticon anticon-down"><svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>存储组件</span> <span class="arrow right"><i aria-label="icon: down" class="anticon anticon-down"><svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>依赖注入组件</span> <span class="arrow right"><i aria-label="icon: down" class="anticon anticon-down"><svg viewBox="64 64 896 896" focusable="false" data-icon="down" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"></path></svg></i></span></p> <!----></section></li></ul> </aside> <main class="page has-page-anchor"> <div class="theme-antdocs-content content__default"><h1 id="接入其他-websocket-客户端"><a href="#接入其他-websocket-客户端" class="header-anchor">#</a> 接入其他 WebSocket 客户端</h1> <p>众所周知,炸毛框架提供了 HTTP、WebSocket 服务器功能,但默认的框架只接收 HTTP 请求和 OneBot 12 标准 的 WebSocket 客户端。</p> <p>想要接入其他 WebSocket 客户端,例如通过浏览器前端、游戏客户端、手机移动端等方式通过 WebSocket 接入框架从而和机器人实现联动,也是很容易的。</p> <h2 id="接入"><a href="#接入" class="header-anchor">#</a> 接入</h2> <p>框架默认只会接入 <code>Sec-WebSocket-Protocol</code> 为 <code>12.xxx</code> 类型的 WS 客户端,同时默认也会断掉所有未设置连接状态信息的 WebSocket 客户端握手请求。</p> <p>所以接入框架只需要写一个 <code>WebSocketOpenEvent</code> 的监听事件,在函数内通过 <code>ConnectionUtil::setConnection()</code> 方法标记该连接有效,框架就不会断掉连接,并保存该连接的信息。</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">BindEvent</span><span class="token punctuation">(</span><span class="token attribute-class-name class-name">WebSocketOpenEvent</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span>
|
||
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">onCustomOpen</span><span class="token punctuation">(</span><span class="token class-name type-declaration">WebSocketOpenEvent</span> <span class="token variable">$event</span><span class="token punctuation">)</span>
|
||
<span class="token punctuation">{</span>
|
||
<span class="token comment">// 例如通过判断 Sec-WebSocket-Protocol 头来识别一个第三方客户端类型</span>
|
||
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">getHeaderLine</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Sec-WebSocket-Protocol'</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token string single-quoted-string">'my-custom-ws-client'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
||
<span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>ZM<span class="token punctuation">\</span>Utils<span class="token punctuation">\</span>ConnectionUtil</span><span class="token operator">::</span><span class="token function">setConnection</span><span class="token punctuation">(</span><span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getFd</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'my-custom-ws-client'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'123'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token comment">// 如果你的客户端要求握手回包中必须返回一个合法的 Sec-WebSocket-Protocol 头,则可以使用下面这行代码来添加额外的 Response Header</span>
|
||
<span class="token variable">$event</span><span class="token operator">-></span><span class="token function">withResponse</span><span class="token punctuation">(</span><span class="token function">zm_http_response</span><span class="token punctuation">(</span><span class="token argument-name">status_code</span><span class="token punctuation">:</span> <span class="token number">101</span><span class="token punctuation">,</span> <span class="token argument-name">headers</span><span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'Sec-WebSocket-Protocol'</span> <span class="token operator">=></span> <span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">getHeaderLine</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Sec-WebSocket-Protocol'</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>上方的例子的 <code>setConnection</code> 第二个参数是一个数组,你可以设置一些自己的键名和键值传入,用于保存该连接对应的信息,此后可以通过 <code>ConnectionUtil::getConnection($fd)</code> 方式获取。</p> <h2 id="接收和发送"><a href="#接收和发送" class="header-anchor">#</a> 接收和发送</h2> <p>接入后,你可以通过 <code>WebSocketMessageEvent</code> 来监听客户端发来的消息帧。当然,这里你需要用到一个内置的中间件,用于限定事件只获取指定类型的事件:</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">BindEvent</span><span class="token punctuation">(</span><span class="token attribute-class-name class-name">WebSocketMessageEvent</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span>
|
||
<span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">Middleware</span><span class="token punctuation">(</span><span class="token attribute-class-name class-name">WebSocketFilter</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'my-custom-ws-client'</span> <span class="token operator">=></span> <span class="token attribute-class-name class-name">true</span><span class="token punctuation">]</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span>
|
||
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">onCustomMessage</span><span class="token punctuation">(</span><span class="token class-name type-declaration">WebSocketMessageEvent</span> <span class="token variable">$event</span><span class="token punctuation">,</span> <span class="token class-name type-declaration">FrameInterface</span> <span class="token variable">$frame</span><span class="token punctuation">)</span>
|
||
<span class="token punctuation">{</span>
|
||
<span class="token function">logger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'收到了自定义 ws 客户端发来的消息事件:'</span> <span class="token operator">.</span> <span class="token variable">$frame</span><span class="token operator">-></span><span class="token function">getData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>这里要注意,这个中间件 <code>WebSocketFilter</code> 的后面数组内为限定查询的参数。这个限定列表支持多个参数,键名为你在 <code>WebSocketOpenEvent</code> 中通过 <code>setConnection()</code> 方法添加的连接信息。</p> <p>这里的例子和上方形成了联动,比如这里使用 <code>['my-custom-ws-client' => true]</code> 的含义就是:
|
||
只要收到的 WebSocket 消息事件所属连接信息存在 <code>my-custom-ws-client</code> 字段,即为真,否则为假(不响应此事件)。</p> <blockquote><p>如果你不使用 <code>WebSocketFilter</code> 中间件做过滤,那么该 BindEvent 绑定的函数将响应所有类型的客户端连接的所有消息帧。</p></blockquote> <p>收到消息后,我们也可以使用 <code>$event->send()</code> 方法发送消息帧到客户端:</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token variable">$event</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'hello world'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 传入字符串时,将自动转换为发送 UTF-8 文本的消息帧</span>
|
||
<span class="token variable">$event</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Choir<span class="token punctuation">\</span>WebSocket<span class="token punctuation">\</span>FrameFactory</span><span class="token operator">::</span><span class="token function">createTextFrame</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'ohuo'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 你也可以直接传入一个符合 FrameInterface 接口的消息帧</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><h2 id="连接断开事件"><a href="#连接断开事件" class="header-anchor">#</a> 连接断开事件</h2> <p>如果客户端主动断开与服务端的连接,服务端会触发 WebSocketCloseEvent 事件,同时伴随一个关闭帧。</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">BindEvent</span><span class="token punctuation">(</span><span class="token attribute-class-name class-name">WebSocketCloseEvent</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span>
|
||
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">onClose</span><span class="token punctuation">(</span><span class="token class-name type-declaration">WebSocketCloseEvent</span> <span class="token variable">$event</span><span class="token punctuation">)</span>
|
||
<span class="token punctuation">{</span>
|
||
<span class="token function">logger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'fd '</span> <span class="token operator">.</span> <span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getFd</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">.</span> <span class="token string single-quoted-string">' 关闭了连接'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h2 id="消息帧"><a href="#消息帧" class="header-anchor">#</a> 消息帧</h2> <p>WebSocket 通信少不了一个概念:消息帧。框架采用了 Choir 的 HTTP 组件,内包含一个 FrameInterface,消息帧的接口类型。
|
||
框架支持发送所有实现了 FrameInterface 的消息帧,例如发送 PING 包、PONG 包、二进制数据包、UTF-8 文本包。</p> <p>框架默认使用的消息帧对象是:<code>\Choir\WebSocket\Frame</code>,你可以使用 FrameFactory 工厂类创建一个 Frame:</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token variable">$frame</span> <span class="token operator">=</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Choir<span class="token punctuation">\</span>WebSocket<span class="token punctuation">\</span>FrameFactory</span><span class="token operator">::</span><span class="token function">createTextFrame</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'hello'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建文本帧</span>
|
||
<span class="token variable">$frame</span> <span class="token operator">=</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Choir<span class="token punctuation">\</span>WebSocket<span class="token punctuation">\</span>FrameFactory</span><span class="token operator">::</span><span class="token function">createBinaryFrame</span><span class="token punctuation">(</span><span class="token function">file_get_contents</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'a.jpg'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建二进制数据帧</span>
|
||
<span class="token variable">$frame</span> <span class="token operator">=</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Choir<span class="token punctuation">\</span>WebSocket<span class="token punctuation">\</span>FrameFactory</span><span class="token operator">::</span><span class="token function">createPingFrame</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建 ping 帧</span>
|
||
<span class="token variable">$frame</span> <span class="token operator">=</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Choir<span class="token punctuation">\</span>WebSocket<span class="token punctuation">\</span>FrameFactory</span><span class="token operator">::</span><span class="token function">createPongFrame</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建 pong 帧</span>
|
||
<span class="token variable">$frame</span> <span class="token operator">=</span> <span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>Choir<span class="token punctuation">\</span>WebSocket<span class="token punctuation">\</span>FrameFactory</span><span class="token operator">::</span><span class="token function">createCloseFrame</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建关闭请求帧,用于主动正常断开 WebSocket 连接,参数为 WebSocket 的状态码,可参考 RFC</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h2 id="事件外主动发送消息帧"><a href="#事件外主动发送消息帧" class="header-anchor">#</a> 事件外主动发送消息帧</h2> <p>在使用 WebSocket 接入客户端时,往往会有不在事件内需要向已连接的客户端发送 WebSocket 消息的情况,框架的 Driver 层抽象了全局方法 <code>ws_socket()</code> 来提供一个可在事件外发送 WS 消息的功能。</p> <p>举例一,我们想在收到一个 HTTP 请求时,发送一条消息到所有已连接的同一类型 WebSocket 客户端。我们在接入客户端的时候,对客户端的 fd 做了缓存:</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">BindEvent</span><span class="token punctuation">(</span><span class="token attribute-class-name class-name">WebSocketOpenEvent</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span>
|
||
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">onWSOpen</span><span class="token punctuation">(</span><span class="token class-name type-declaration">WebSocketOpenEvent</span> <span class="token variable">$event</span><span class="token punctuation">)</span>
|
||
<span class="token punctuation">{</span>
|
||
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">getHeaderLine</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Sec-WebSocket-Protocol'</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token string single-quoted-string">'special-app'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
||
<span class="token function">logger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'special-app 已接入,正在鉴权'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token comment">// 为了更贴近真实开发案例,这里假装通过 GET 请求传入的 token 参数进行一个鉴权,实际业务的鉴权逻辑请自行编写!</span>
|
||
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">getQueryParams</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'token'</span><span class="token punctuation">]</span> <span class="token operator">??</span> <span class="token constant">null</span><span class="token punctuation">)</span> <span class="token operator">!==</span> <span class="token string single-quoted-string">'emhhbWFvLWZyYW1ld29yaw=='</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
|
||
<span class="token function">logger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">warning</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'客户端 ['</span> <span class="token operator">.</span> <span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getFd</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">.</span> <span class="token string single-quoted-string">'] 鉴权失败'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token keyword">return</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
<span class="token function">logger</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">info</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'鉴权成功!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token class-name class-name-fully-qualified static-context"><span class="token punctuation">\</span>ZM<span class="token punctuation">\</span>Utils<span class="token punctuation">\</span>ConnectionUtil</span><span class="token operator">::</span><span class="token function">setConnection</span><span class="token punctuation">(</span><span class="token variable">$event</span><span class="token operator">-></span><span class="token function">getFd</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'special-app'</span> <span class="token operator">=></span> <span class="token function">time</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
<span class="token punctuation">}</span>
|
||
|
||
<span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">Route</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/ws-test/{name}'</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span>
|
||
<span class="token keyword">public</span> <span class="token keyword">function</span> <span class="token function-definition function">onRouteTest</span><span class="token punctuation">(</span><span class="token keyword type-hint">array</span> <span class="token variable">$params</span><span class="token punctuation">)</span>
|
||
<span class="token punctuation">{</span>
|
||
<span class="token comment">// 这行的 ws_socket 传入的参数 1 为多 server 对应的 flag 参数,留空则默认使用 1。(框架的默认配置第一个 websocket 的 flag 也是 1)</span>
|
||
<span class="token comment">// sendMultiple 的作用在于同时到多个客户端,第二个参数是一个回调函数,可以用它来过滤选择自己相应连接</span>
|
||
<span class="token function">ws_socket</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">sendMultiple</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'收到了网页请求,它说它是 '</span> <span class="token operator">.</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">fn</span> <span class="token punctuation">(</span><span class="token variable">$fd</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token class-name static-context">ConnectionUtil</span><span class="token operator">::</span><span class="token function">getConnection</span><span class="token punctuation">(</span><span class="token variable">$fd</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'special-app'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token comment">// 创建一个 HTTP Response 返回用户网页</span>
|
||
<span class="token keyword">return</span> <span class="token function">zm_http_response</span><span class="token punctuation">(</span><span class="token argument-name">body</span><span class="token punctuation">:</span> <span class="token string single-quoted-string">'hello, '</span> <span class="token operator">.</span> <span class="token variable">$params</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'name'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
<span class="token punctuation">}</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p>除此之外,你也可以使用 <code>ws_socket()->send()</code> 方法,只给一个客户端发送消息帧,通过指定第二个参数 fd 来实现:</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token function">ws_socket</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">-></span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'hello'</span><span class="token punctuation">,</span> <span class="token variable">$fd</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>另外,对于开发上的考虑,对于在事件外挑选一个客户端发送消息时,涉及 fd 存储的问题,你可以配合 <code>kv()</code>、<code>db()</code> 等组件对 fd 进行缓存。</p> <h2 id="多服务器端口"><a href="#多服务器端口" class="header-anchor">#</a> 多服务器端口</h2> <p>框架 3.0 支持了同时监听多个端口,例如框架默认的配置就同时监听了 20001、20002 分别做 WebSocket 服务端和 HTTP 服务端。你也可以继续让框架添加多个端口进行监听。</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token comment">// global.php</span>
|
||
<span class="token comment">/* 要启动的服务器监听端口及协议 */</span>
|
||
<span class="token variable">$config</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'servers'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>
|
||
<span class="token punctuation">[</span>
|
||
<span class="token string single-quoted-string">'host'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'0.0.0.0'</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'port'</span> <span class="token operator">=></span> <span class="token number">20001</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'websocket'</span><span class="token punctuation">,</span>
|
||
<span class="token punctuation">]</span><span class="token punctuation">,</span>
|
||
<span class="token punctuation">[</span>
|
||
<span class="token string single-quoted-string">'host'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'0.0.0.0'</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'port'</span> <span class="token operator">=></span> <span class="token number">20002</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'http'</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'flag'</span> <span class="token operator">=></span> <span class="token number">20002</span><span class="token punctuation">,</span>
|
||
<span class="token punctuation">]</span><span class="token punctuation">,</span>
|
||
<span class="token punctuation">[</span>
|
||
<span class="token string single-quoted-string">'host'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'0.0.0.0'</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'port'</span> <span class="token operator">=></span> <span class="token number">20003</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'type'</span> <span class="token operator">=></span> <span class="token string single-quoted-string">'websocket'</span><span class="token punctuation">,</span>
|
||
<span class="token string single-quoted-string">'flag'</span> <span class="token operator">=></span> <span class="token number">4</span><span class="token punctuation">,</span>
|
||
<span class="token punctuation">]</span><span class="token punctuation">,</span>
|
||
<span class="token punctuation">]</span><span class="token punctuation">;</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br></div></div><p>每个服务端支持四个参数,<code>host</code>、<code>port</code>、<code>type</code>、<code>flag</code>。其中 flag 参数可忽略,忽略则默认值为 1。</p> <p>flag 的用处就是在事件内区分来源服务监听的端口,例如上方的配置,我监听了两个 websocket 的端口,第一个 flag 是 1,第二个 flag 是 4。</p> <p>我们在 WebSocket 的三种事件(WebSocketOpenEvent、WebSocketMessageEvent、WebSocketCloseEvent)中,均可使用 WebSocketFilter 中间件进行过滤限定 flag。
|
||
下方为一个 Open 事件使用 Filter 过滤端口 20003 来源的客户端连接:</p> <div class="language-php line-numbers-mode"><pre class="language-php"><code><span class="token attribute"><span class="token delimiter punctuation">#[</span><span class="token attribute-content"><span class="token attribute-class-name class-name">BindEvent</span><span class="token punctuation">(</span><span class="token attribute-class-name class-name">WebSocketOpenEvent</span><span class="token operator">::</span><span class="token constant">class</span><span class="token punctuation">)</span></span><span class="token delimiter punctuation">]</span></span>
|
||
#<span class="token punctuation">[</span><span class="token function">Middleware</span><span class="token punctuation">(</span><span class="token class-name static-context">WebSocketFilter</span><span class="token operator">::</span><span class="token keyword">class</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string single-quoted-string">'flag'</span> <span class="token operator">=></span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">]</span>
|
||
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/zhamao-robot/zhamao-framework/edit/main/docs/components/http/websocket-access.md" target="_blank" rel="noopener noreferrer">Edit this page</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev"><a href="/components/http/zmrequest.html" class="prev"><i aria-label="icon: left" class="anticon anticon-left"><svg viewBox="64 64 896 896" focusable="false" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 0 0 0 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></i>
|
||
ZMRequest HTTP 客户端
|
||
</a></span> <span class="next"><a href="/components/http/websocket-client.html">
|
||
框架内置 WebSocket 客户端
|
||
<i aria-label="icon: right" class="anticon anticon-right"><svg viewBox="64 64 896 896" focusable="false" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></i></a></span></p></div> <div class="page-anchor"><div class="ant-space ant-space-vertical" style="width:100%;"><div class="ant-space-item"><div class="page-anchor-offset"><div><div class="ant-anchor-wrapper" style="max-height:100vh;"><div class="ant-anchor"><div class="ant-anchor-ink"><span class="ant-anchor-ink-ball"></span></div><div class="ant-anchor-link"><a href="#接入" title="接入" class="ant-anchor-link-title">接入</a></div><div class="ant-anchor-link"><a href="#接收和发送" title="接收和发送" class="ant-anchor-link-title">接收和发送</a></div><div class="ant-anchor-link"><a href="#连接断开事件" title="连接断开事件" class="ant-anchor-link-title">连接断开事件</a></div><div class="ant-anchor-link"><a href="#消息帧" title="消息帧" class="ant-anchor-link-title">消息帧</a></div><div class="ant-anchor-link"><a href="#事件外主动发送消息帧" title="事件外主动发送消息帧" class="ant-anchor-link-title">事件外主动发送消息帧</a></div><div class="ant-anchor-link"><a href="#多服务器端口" title="多服务器端口" class="ant-anchor-link-title">多服务器端口</a></div></div></div></div></div></div></div></div> </main> <!----></div><div class="global-ui"></div></div>
|
||
<script src="/assets/js/app.cf958133.js" defer></script><script src="/assets/js/2.4c04991c.js" defer></script><script src="/assets/js/1.d8755a39.js" defer></script><script src="/assets/js/38.75fa7a1c.js" defer></script>
|
||
</body>
|
||
</html> |