视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Think-Swoole教程之WebSocket的介绍、事件和数据发送
2020-11-02 18:02:00 责编:小采
文档

什么是 WebSocket

WebSocket 协议是基于 TCP 的一种新的网络协议,使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

为什么需要 WebSocket

因为 HTTP 的通信只能由客户端发起。

WebSocket有哪些特点

  • 建立在TCP协议之上的

  • 性能开销小,通信高效

  • 客户端可以与任意的服务器进行通信

  • 协议标识:ws、wss

  • 持久化网络通信协议

  • WebSocket 使用场景

    社交聊天、弹幕、多玩家游戏、协同编辑、股票基金实时报价、体育实况更新、视频会议聊天、基于位置的应用、在线教育等需要高实时性的运用场景。

    在 WebSocket 之前,传统方式我们想要做聊天程序,可能会使用 JavaScript 定时器,每隔一秒钟发送一次 HTTP 请求到服务器,查询有没有新消息。

    有了 WebSocket ,客户端通过浏览器以 HTTP 方式向服务端发送 WebSocket 连接请求,然后服务器发出回应,这个过程通常称为“握手” 。浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道,将协议升级为 WebSocket,有新消息的话,服务端主动将消息推送给客户端。

    SocketIO 又是什么

    WebSocket 是 HTML5 最新提出的规范,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况,为了兼容所有浏览器,给程序员提供一致的编程体验, SocketIO 将 WebSocket 、AJAX 和其它的通信方式全部封装成了统一的通信接口,也就是说,我们在使用 SocketIO 时,不用担心兼容问题,底层会自动选用最佳的通信方式。因此说,WebSocket 是 SocketIO 的一个子集,Think-Swoole 中是按照 SocketIO 进行解析发送到服务端的数据。

    在 ThinkPHP 6 中开启 WebSocket 服务

    1、配置文件 config/swoole.php 中“websocket. enable”设置为 true。

    2、创建监听事件,创建WsConnect、WsClose、WsTest(这个可任意命名,和客户端须对应起来),在项目根目录分别输入如下命令:

    php think make:listener WsConnect
    php think make:listener WsClose
    php think make:listener WsTest

    app/listener 目录下会生成刚才创建的监听类文件,在对应的事件类中可写入业务逻辑。我们这里先打印 $event 这个变量。Connect 事件中的 $event 是 appRequest 请求对象,Test自定义消息接收事件的 $event 是客户端发送过来的消息。

    3、在 app/event.php 中的数组 listen 键中定义事件监听类:

    app/event.php
    'listen' => [
     'AppInit' => [],
     'HttpRun' => [],
     'HttpEnd' => [],
     'LogLevel' => [],
     'LogWrite' => [],
     //监听连接,swoole 事件必须以 swoole 开头
     'swoole.websocket.Connect' => [
     applistenerWsConnect::class
     ],
     //监听关闭
     'swoole.websocket.Close' => [
     applistenerWsClose::class
     ],
     //监听 Test 场景
     'swoole.websocket.Test' => [
     applistenerWsTest::class
     ],
     ],

    swoole.websocket.Connect:客户端与服务器建立连接并完成握手事件,即 Swoole 中的 onOpen 事件。在这里记录你自己程序用户与客户端的连接ID(fd)等。非必须,建议定义。

    swoole.websocket.Close:客户端连接关闭事件,非必须。

    swoole.websocket.Test:自定义的 Test 事件;用于接收客户端发送的 test 事件的消息。一个项目中可以定义多个 Test 事件,例如聊天、定位、客服功能事件,则可对应为 Test1、Test2、Test3等。

    WebSocket 的事件也可以在 config/swoole.php 配置文件的“websocket. listen”进行配置:

    'listen' => [
     // 首字母大小写都可以;值应该是字符串非数组
     'connect' => 'applistenerWsConnect',
     'close' => 'applistenerWsClose',
     'test' => 'applistenerWsTest'
    ],

    4、项目根目录开启服务:php think swoole start 即可,底层会自动判断当前请求是 HTTP 还是 WebSocket。

    客户端与服务端建立连接

    现在我们做一个 HTML 页面,通过 HTML5 WebSocket 向我们的服务器端建立连接。在任意地方新建 test.html,内容如下:

    <!DOCTYPE HTML>
    <html>
    <head>
     <meta charset="UTF-8">
     <title>Document</title>
    </head>
    <body>
    
    消息:<input type="text" id="message">
    接收者:<input type="text" id="to">
    <button onclick="send()">发送</button>
    <script>
     var ws = new WebSocket("ws://127.0.0.1:9501/");
     ws.onopen = function(){
     console.log('连接成功');
     }
     ws.onmessage = function(data){
     console.log(data);
     }
     ws.onclose = function(){
     console.log('连接断开');
     }
     function send()
    {
     var message = document.getElementById('message').value;
     var to = document.getElementById('to').value;
     console.log("准备给" + to + "发送数据:" + message);
     ws.send(JSON.stringify(['test',{
     //这里可以自己定义属性
     to:to,
     message:message
     }])); //发送的数据必须是 "['test',数据]" 这种格式
     }
    </script>
    </body>
    </html>

    HTML5 WebSocket 有关介绍,可以访问这里进行学习。

    前端代码中 var ws = new WebSocket("ws://127.0.0.1:9501/"); 我的服务器是在本地,swoole.php 配置文件中配置的端口号是 9501,所以访问127.0.0.1:9501,ws 是 WebSocket 协议,与 HTTP、HTTPS 一样,它有 WS 和 WSS 协议。ws.onmessage 可以接受消息。

    接下来通过浏览器访问这个 HTML 页面,并打开浏览器调试控制台,可以看到连接成功的字样,以及服务端打印出来的参数:

    然后我们在刚才创建的 HTML 页面的输入框中发送消息,控制台中打印出了我们的信息:

    Swoole 监听服务终端中,也收到了我们发送过来的消息:

    这是因为我们在 app/listener/WsTest 打印了 $event 变量。

    最后说明一下前端页面中 ws.send(JSON.stringify(['test',{to:to,message:message}])); 这段代码,JSON.stringify() 的作用是将 JavaScript 对象转换为 JSON 字符串,to 和 message 属性是我们自定义的,test 是后端定义的 Test 事件,这个名称一定和后端对应起来。由于think-swoole中是按照 SocketIO 进行解析发送过来的数据,所以你发送的数据应该是 “[‘事件名’, 真正要发送的数据]” 的字符串形式:第一个参数的 test 就是对应服务器端的Test 事件,用于区分更多场景的实时通信逻辑业务;第二个参数才是你真正发送的数据,可以是字符串、数据、对象,服务器端 $event 参数获取的就是它。

    下载本文
    显示全文
    专题