什么是 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 是 app\Request 请求对象,Test自定义消息接收事件的 $event 是客户端发送过来的消息。
3、在 app/event.php 中的数组 listen 键中定义事件监听类:
app/event.php 'listen' => [ 'AppInit' => [], 'HttpRun' => [], 'HttpEnd' => [], 'LogLevel' => [], 'LogWrite' => [], //监听连接,swoole 事件必须以 swoole 开头 'swoole.websocket.Connect' => [ app\listener\WsConnect::class ], //监听关闭 'swoole.websocket.Close' => [ \app\listener\WsClose::class ], //监听 Test 场景 'swoole.websocket.Test' => [ \app\listener\WsTest::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' => 'app\listener\WsConnect', 'close' => 'app\listener\WsClose', 'test' => 'app\listener\WsTest' ],
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 参数获取的就是它。
以上是Think-Swoole教程之WebSocket的介绍、事件和数据发送的详细内容。更多信息请关注PHP中文网其他相关文章!