微信小程序WebSocket开发
image让我们来实现一个简单的微信小程序WebSocket。WebSocket是一种没有被规范化的网络协议,不过网络上又有文章说是2011年被国际化。不过不管怎么样它摆脱了Http的无状态特性。什么是无状态,我看文章的时候有句话好经典:“人生若只如初见”。这句话完美的诠释了无状态。而WebSocket可以建立一种双向通道,即客户端可以通过此通道(Tcp)与服务器相互沟通,而服务器也可以通过此通道(Tcp)实现与服务器的沟通。而不必等待客户端的请求后再沟通。
注意WebSocket是一种协议,所以你需要让你的服务器能够解析这个协议。由于是Tcp为底层的,所以解析这个协议主要是“握手”。由于我的后台采用PHP编写,所以主要讲一下PHP的WebSocket利用。这个搭建过程你可以参考:http://www.iwonmo.com/archives/1287.html
两点注意:
1、使用php cli模式来运行你的WebSocket代码。
2、new对象的时候要new swoole_websocket_server。
如果你看过搭建过程了的话,那么下面这段代码你并不陌生了。
$server = new swoole_websocket_server("0.0.0.0", 你的WebSocket端口);
$server->on('open', function (swoole_websocket_server $server, $request) {
echo "server: handshake success with fd{$request->fd}\n";
});
$server->on('message', function (swoole_websocket_server $server, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$server->push($frame->fd, "this is server");
});
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
$server->start();
这里要注意你的nginx的反射端口,如果这个不会配置的话,可以留言。我将我的配置文档发送给你。
要实现微信小程序访问wss你还需要在你的微信小程序后台也就是微信的网站页面添加你的wss地址。这里的地址你可以通过nginx来设置,不过要注意要有ssl证书,这个证书你可以在阿里云申请。然后你可以新建你的小程序了。
注意swoole官网的一段话。
onRequest回调
swoole_websocket_server 继承自 swoole_http_server
设置了onRequest回调,websocket服务器也可以同时作为http服务器
未设置onRequest回调,websocket服务器收到http请求后会返回http 400错误页面
如果想通过接收http触发所有websocket的推送,需要注意作用域的问题,面向过程请使用global对swoole_websocket_server进行引用,面向对象可以把swoole_websocket_server设置成一个成员属性
所以说如果你访问网址后出现400错误,不要惊慌。因为你查看request你会发现你并没有实现它。如果实现了就不会出现400。而是空白。
<?php
$server = new swoole_websocket_server("0.0.0.0", 你的WebSocket端口);
//握手完毕后回调函数
$server->on('open', function (swoole_websocket_server $server, $request) {
echo "server: handshake success with fd{$request->fd}\n";
// $server->push($request->fd, "this is server");
});
//有消息到达时的回调函数
$server->on('message', function (swoole_websocket_server $server, $frame) {
echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
$server->push($frame->fd, "客户端消息:receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n");
$server->push($frame->fd, "my server\n");
});
//关闭时的一个回调
$server->on('close', function ($ser, $fd) {
echo "client {$fd} closed\n";
});
//协议头
$server->on('request', function (swoole_http_request $request, swoole_http_response $response) {
global $server;//调用外部的server
// $server->connections 遍历所有websocket连接用户的fd,给所有用户推送
foreach ($server->connections as $fd) {
$server->push($fd, $request->get['message']);
}
});
$server->start();
上述代码是我服务器的一段代码。可以看到首先New了一个swoole对象。然后接管了几个回调。注意的是swoole的websocket向客户端发送数据采用的是push而不是send。在来看一下微信小程序的JavaScript代码。
wx.connectSocket({
url: 'wss://xxxxxx.com'
})
wx.onSocketOpen(function (res) {
console.log('WebSocket连接已打开!')
wx.sendSocketMessage({
data: "aa"
})
})
wx.onSocketMessage(function (res) {
console.log('收到服务器内容:' + res.data)
wx.closeSocket()
})
wx.onSocketClose(function (res) {
console.log('WebSocket 已关闭!')
})
wx.onSocketError(function (res) {
console.log('WebSocket连接打开失败,请检查!')
})
基本上都是官网的代码。代码里的方法可以参考微信小程序官网的API文档来查看。我这里主要是发送了一个文本数据给swoole框架,然后框架解析出我的数据类型与数据相关的一些信息。这个在swoole的官网API有解释。
onMessage
当服务器收到来自客户端的数据帧时会回调此函数。
-
$frame 是swoole_websocket_frame对象,包含了客户端发来的数据帧信息
-
onMessage回调必须被设置,未设置服务器将无法启动
-
客户端发送的
ping
帧不会触发onMessage
,底层会自动回复pong
包
swoole_websocket_frame
共有4个属性,分别是
-
$frame->fd,客户端的socket id,使用$server->push推送数据时需要用到
-
$frame->data,数据内容,可以是文本内容也可以是二进制数据,可以通过opcode的值来判断
-
$frame->opcode,WebSocket的OpCode类型,可以参考WebSocket协议标准文档
-
$frame->finish, 表示数据帧是否完整,一个WebSocket请求可能会分成多个数据帧进行发送(底层已经实现了自动合并数据帧,现在不用担心接收到的数据帧不完整)
$data 如果是文本类型,编码格式必然是UTF-8,这是WebSocket协议规定的
OpCode与数据类型
-
WEBSOCKET_OPCODE_TEXT = 0x1 ,文本数据
-
WEBSOCKET_OPCODE_BINARY = 0x2 ,二进制数据
小问题:如果会话关闭后,cli也关闭了。导致无法访问,你可以尝试下面这个方法:http://www.iwonmo.com/archives/1292.html
Swoole开发文档:https://wiki.swoole.com/wiki/page/397.html
微信小程序WebSocket开发文档:https://developers.weixin.qq.com/miniprogram/dev/api/network-socket.html
也可以访问我的博客:http://www.iwonmo.com
网友评论