首页 > PHP资讯 > 工具库 > 微信小程序开发之websocket实例详解

微信小程序开发之websocket实例详解

工具库

为什么需要websocket?

传统的实时交互的游戏,或服务器主动发送消息的行为(如推送服务),如果想做在微信上,可能你会使用轮询的方式进行,不过这太消耗资源,大量的请求也加重了服务器的负担,而且延迟问题比较严重。如果是自己开发的app,为了解决这些问题,很多团队会自建socket,使用tcp长链接、自定协议的方式与服务器进行相对实时的数据交互。有能力的团队,采用这种方式自然没什么大问题。不过小团队可能就要花费很多时间去调试,要解决很多难题,这个在成本上就划不来。

H5引入了webSocket来解决网页端的长链接问题,而微信小程序也支持websocket。这是一个非常重要的特性,所以本系列的文章会专门拿出一篇来讨论websocket。

webSocket本质上也是TCP连接,它提供全双工的数据传输。一方面可以避免轮询带来的连接频繁建立与断开的性能损耗,另一方面数据可以是比较实时的进行双向传输(因为是长链接),而且WebSocket允许跨域通信(这里有个潜在的跨域安全的问题,得靠服务端来解决)。目前除IE外的浏览器已经对webSocket支持得很好了,微信小程序再推一把之后,它会变得更加流行。

我们来设计一个新的demo,一个比较有趣的小游戏,多人版扫雷,准确地讲,多人版挖黄金。

-1表示金子。看了下貌似没什么问题。接下去,我们就要接入webSocket了。

(这个是js版本的,其实生成地图场景的工作是在后台生成,这个js版本只是一个演示,不过算法是一样的。)

2、我们需要一个支持webSocket的服务端

本例子中,我们使用python的tornado框架来实现(tornado提供了tornado.websocket模块)。当然读者也可以使用socket.io,专为webSocket设计的js语言的服务端,用起来非常简单,它也对不支持webSocket的浏览器提供了兼容(flash或comet实现)。

笔者本人比较喜欢使用tornado,做了几年后台开发,使用最多的框架之一的就是它,NIO模型,而且非常轻量级,同样的rps,java可能需要700-800M的内存,tornado只要30-40M,所以在一台4G内存的机子上可以跑上百个tornado服务,而java,对不起,只能跑3个虚拟机。微服务的时代,这一点对小公司很重要。当然如果读者本人对java比较熟悉的话,也可以选择netty框架尝试一下。

webSocket用tornado的另一个好处是,它可以在同一个服务(端口)上同时支持webSocket及http两种协议。tornado的官方demo代码中展示了怎么实现同时使用两种协议。在本游戏中,可以这么用:用户进入首页,用http协议去拉取当前的房间号及数据。因为首页是打开最多的,进了首页的用户不一定会玩游戏。所以首页还没必要建立webSocket链接,webSocket链接主要用来解决频繁请求及推送的操作。首页只有一个请求操作。选了房间号后,进去下一个游戏页面再开始建立webSocket链接。

3、客户端

使用微信小程序开发工具,直接连接是会报域名安全错误的,因为工具内部做了限制,对安全域名才会允许连接。所以同样的,这里我们也继续改下工具的源码,把相关的行改掉就行修改方式如下:

找到asdebug.js的这一行,把它改成: if(false)即可。

`if (!i(r, "webscoket"))

懒得修改的读者可以直接使用我破解过的IDE。 发起一个websocket链接的代码也比较简单:

`wx.connectSocket({url: webSocketUrl,});
在调用这个请求代码之前,先添加下事件监听,这样才知道有没有连接成功:
`

wx.onSocketOpen(function(res){ console.log('websocket opened.'); });

`连接失败的事件:
wx.onSocketError(function(res){ console.log('websocket fail');}) `

收到服务器的消息时触发的事件:

`wx.onSocketMessage(function(res){console.log('received msg: ' + res.data);})
当链接建立之后,发送消息的方法如下:
`

消息发送

由于建立链接是需要几次握手,需要一定的时间,所以在wx.connectSocket成功之前,如果直接wx.sendSocketMessage发送消息会报错,这里做一个兼容,如果连接还没建立成功,则用一个数组来保存要发送的信息;而链接第一次建立时,把数据遍历一遍,把消息拿出来一个个补发。这个逻辑我们封装成一个send方法,如下:

`function sendSocketMessage(msg) {if (typeof(msg) === 'object') { // 只能发送stringmsg = JSON.stringify(msg);}if (socketOpened) { // socketOpened变量在wx.onSocketOpen时设置为truewx.sendSocketMessage({data:msg});} else { // 发送的时候,链接还没建立socketMsgQueue.push(msg);}}

二、demo功能解析

1、首页entry

为了简化模型,把重点放在webSocket上,我们把首页做成自己填写房间号的形式。读者如果自己有时间和能力的话,可以把首页做成一个房间列表,并显示每个房间有多少人在玩,只有一人的可以进去跟他玩。甚至后面还可以加上观看模式,点击别人的房间进去观看别人怎么玩。

3、前端挖金子

代码如下:

var websocket = require('../../websocket/connect.js'); var msgReceived = require('../../websocket/msgHandler.js');Page({    data: {        mimeMap: null,        leftGolds: 0, // 总共有多少金子 score: 0, // 我的得分 roomNo: 0 // 房间号 },    x: 0, // 用户点中的列 y: 0, // 用户点中的行 onLoad: function () { var roomNo = app.getRoomNo(); this.setData({            roomNo: roomNo        }); // test // websocket.send('before connection'); if (!websocket.socketOpened) { // setMsgReceiveCallback websocket.setReceiveCallback(msgReceived, this); // connect to the websocket websocket.connect();            websocket.send({              type: 'create' });        } else {            websocket.send({              type: 'create',              no: roomNo            });        }    },    digGold: function(event) { // 不直接判断,而把坐标传给后台判断 // 被开过的就不管了 if (event.target.dataset.value < 9) { return;        } // 取到这格的坐标 this.x = parseInt(event.target.dataset.x); this.y = parseInt(event.target.dataset.y); console.log(this.x, this.y); // 上报坐标 this.reportMyChoice();    },    reportMyChoice: function() {        roomNo = app.getRoomNo();        websocket.send({            type: 'dig',            x: this.x,            y: this.y,            no: roomNo        });    },});

在page的onLoad事件里,先更新界面上的房间号信息。然后开始我们的重点,websocket.connect发起webSocket链接,websocket是我们封装的模块。然后把我们msgHandler.js处理逻辑设置到服务端推送消息回调里面。接着,发送一个create消息来创建或加入房间。服务端会对这个消息做出响应,返回本房间的地图场景数据。

digGold是每个格子的点击事件处理函数。这儿有一个逻辑,一个格子周边最多有8个格子,所以每个格子的数据最大不可能大于8,上面代码中可以看到有一个9,这其实是为了跟0区分,用来表示场上目前的还没被翻开的格子的数据,用9来表示,当然你也可以用10,100都行。

wxml的矩阵数据绑定代码如下:

`

4、服务端实现

简单的提一下就好,因为后台不是本系列文章的重点,虽然这个demo的开发也花了大半的时候在写后台。前后端的消息交互,借助了webSocket通道,传输我们自己定义格式的内容。上面有个截图显示了后台代码目录的结构,划分得比较随意,handlers里存放了的是主要的处理逻辑。webSocketHandler是入口,在它的on_message里,对收到的客户端的消息,根据类型进行分发,dig类型,分发到answerHandler去处理,create类型,分发到roomHandler里去处理。

还有一点稍微提一下,本例子中的后台webSocket消息处理也跟传统的http处理流程有一点不一样。就是在最后返回的时候,不是直接返回的,而是广播的形式,把消息发送给所有的人。比如用户A点击了格子,后台收到坐标后,会把这个坐标及坐标里的数据一起发送给房间里的所有人,而不是单独返回给上报坐标的人。只是会有一个isMe字段来告诉客户端是否是自己的操作。

总之,在做webSocket开发的时候,上面提到的,前后端都可能会有一些地方跟传统的http接口开发不太一样。读者尝试在做webSocket项目的时候,转换一下思维。

最后提下一个注意点:微信小程序的websocket链接是全局只能有一个,官方提示:“ 一个微信小程序同时只能有一个 WebSocket 连接,如果当前已存在一个 WebSocket 连接,会自动关闭该连接,并重新创建一个 WebSocket 连接。 ”

以上就是微信小程序开发之websocket实例详解的详细内容,更多请关注php中文网其它相关文章!

工具库

本文由欣才IT学院整理发布,未经许可,禁止转载。
支持40不支持0