什么是 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 wsconnectphp think make:listener wsclosephp 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的介绍、事件和数据发送的详细内容。