小程序API wx.connectSocket() 连接WebSocket错误
console:WebSocket connection to 'wss://localhost:5757/api/tunnel' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED
client
this.socketTask = wx.connectSocket({
url: 'wss://localhost:5757/api/tunnel',
})
server
route
// GET 用来响应请求信道地址的
router.get('/tunnel', controllers.tunnel.get)
// POST 用来处理信道传递过来的消息
router.post('/tunnel', controllers.tunnel.post)
controllers
const { tunnel } = require('../qcloud')
const debug = require('debug')('koa-weapp-demo')
/**
* 这里实现一个简单的聊天室
* userMap 为 tunnelId 和 用户信息的映射
* 实际使用请使用数据库存储
*/
const userMap = {}
// 保存 当前已连接的 WebSocket 信道ID列表
const connectedTunnelIds = []
/**
* 调用 tunnel.broadcast() 进行广播
* @param {String} type 消息类型
* @param {String} content 消息内容
*/
const $broadcast = (type, content) => {
tunnel.broadcast(connectedTunnelIds, type, content)
.then(result => {
const invalidTunnelIds = result.data && result.data.invalidTunnelIds || []
if (invalidTunnelIds.length) {
console.log('检测到无效的信道 IDs =>', invalidTunnelIds)
// 从 userMap 和 connectedTunnelIds 中将无效的信道记录移除
invalidTunnelIds.forEach(tunnelId => {
delete userMap[tunnelId]
const index = connectedTunnelIds.indexOf(tunnelId)
if (~index) {
connectedTunnelIds.splice(index, 1)
}
})
}
})
}
/**
* 调用 TunnelService.closeTunnel() 关闭信道
* @param {String} tunnelId 信道ID
*/
const $close = (tunnelId) => {
tunnel.closeTunnel(tunnelId)
}
/**
* 实现 onConnect 方法
* 在客户端成功连接 WebSocket 信道服务之后会调用该方法,
* 此时通知所有其它在线的用户当前总人数以及刚加入的用户是谁
*/
function onConnect (tunnelId) {
console.log(`[onConnect] =>`, { tunnelId })
if (tunnelId in userMap) {
connectedTunnelIds.push(tunnelId)
$broadcast('people', {
'total': connectedTunnelIds.length,
'enter': userMap[tunnelId]
})
} else {
console.log(`Unknown tunnelId(${tunnelId}) was connectd, close it`)
$close(tunnelId)
}
}
/**
* 实现 onMessage 方法
* 客户端推送消息到 WebSocket 信道服务器上后,会调用该方法,此时可以处理信道的消息。
* 在本示例,我们处理 `speak` 类型的消息,该消息表示有用户发言。
* 我们把这个发言的信息广播到所有在线的 WebSocket 信道上
*/
function onMessage (tunnelId, type, content) {
console.log(`[onMessage] =>`, { tunnelId, type, content })
switch (type) {
case 'speak':
if (tunnelId in userMap) {
$broadcast('speak', {
'who': userMap[tunnelId],
'word': content.word
})
} else {
$close(tunnelId)
}
break
default:
break
}
}
/**
* 实现 onClose 方法
* 客户端关闭 WebSocket 信道或者被信道服务器判断为已断开后,
* 会调用该方法,此时可以进行清理及通知操作
*/
function onClose (tunnelId) {
console.log(`[onClose] =>`, { tunnelId })
if (!(tunnelId in userMap)) {
console.log(`[onClose][Invalid TunnelId]=>`, tunnelId)
$close(tunnelId)
return
}
const leaveUser = userMap[tunnelId]
delete userMap[tunnelId]
const index = connectedTunnelIds.indexOf(tunnelId)
if (~index) {
connectedTunnelIds.splice(index, 1)
}
// 聊天室没有人了(即无信道ID)不再需要广播消息
if (connectedTunnelIds.length > 0) {
$broadcast('people', {
'total': connectedTunnelIds.length,
'leave': leaveUser
})
}
}
module.exports = {
// 小程序请求 websocket 地址
get: async ctx => {
const data = await tunnel.getTunnelUrl(ctx.req)
console.log(22222222222222222, data)
const tunnelInfo = data.tunnel
userMap[tunnelInfo.tunnelId] = data.userinfo
ctx.state.data = tunnelInfo
},
// 信道将信息传输过来的时候
post: async ctx => {
const packet = await tunnel.onTunnelMessage(ctx.request.body)
debug('Tunnel recive a package: %o', packet)
switch (packet.type) {
case 'connect':
onConnect(packet.tunnelId)
break
case 'message':
onMessage(packet.tunnelId, packet.content.messageType, packet.content.messageContent)
break
case 'close':
onClose(packet.tunnelId)
break
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论