# wx_webSocket **Repository Path**: windgap/wx_webSocket ## Basic Information - **Project Name**: wx_webSocket - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-10-10 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## node + WebSocket 微信小程序聊天室 [github:https://github.com/fancaixia/wx_webSocket](https://github.com/fancaixia/wx_webSocket) ![https://github.com/fancaixia/wx_websoket/blob/master/pic/chat.png](https://github.com/fancaixia/wx_websoket/blob/master/pic/chat.png)

### 案例思路: [1] ***用户进入聊天室***
- 前台向后台发送连接请求并携带用户id
- 后台 let clients:[]
- clients.push(ws:'socket对象',id:'用户id')
- 向前台广播当前聊天室人数
[2] ***用户退出聊天室***
- 后台遍历clients 查找与当前用户id 对应数据在cliens中删除
- 向前台广播当前聊天室人数
[3] ***聊天室用户发普通消息时***
- 后台收到消息并且向每个ws对象广播消息
[4] ***聊天室用户发图片时***
- 先将图片上传至服务器 (server / upload 目录)
- 然后广播 图片地址
- 前台接收图片路径并渲染页面
`前台接收消息类型 type: message(普通消息) / image(图片消息) / loginin(进入聊天室) / loginout(退出聊天室)`
***~~~未解决: 微信小程序中onSocketOpen 在真机上不触发回调~~~***
***~~~后端数据存储没做研究~~***
### 代码结构: ##### 服务端代码 >server >>node_modules        项目依赖文件
router        处理上传文件模块
upload        图片上传目录
utils        工具函数
app.js        node主文件
##### 小程序端代码 > static >>utils        配置http及ws 地址
pages
>>> home        首页,处理websocket 连接
chat        聊天室页面
### 项目启动: cd / server
cnpm install
npm run dev
##### 小程序端模拟多人聊天 copy static
***static / app.js 修改 UserId 然后进入聊天室(前台根据 UserId 判断发送消息人 )*** ### 小程序代码片段: pages / home / index.js ``` // pages/home/index.js let config = require('../../utils/config.js') let app = getApp(); Page({ data: { }, onLoad: function (options) { }, // 创建 websocket 连接 webSocket(user_id) { //loading 动画 wx.showNavigationBarLoading() // 创建Socket 对象 app.globalData.SocketTask = wx.connectSocket({ url: `${config.wsAddress}?id=${user_id}`, data: '', header: { 'content-type': 'application/json' }, method: 'post', success: function (res) { console.log('WebSocket连接创建', res) }, fail: function (err) { wx.showToast({ title: '网络异常!', }) console.log(err) }, }) app.globalData.SocketTask.onOpen(res => { console.log('WebSocket 连接打开', res) wx.hideNavigationBarLoading() wx.navigateTo({ url: '/pages/chat/index' }) }) app.globalData.SocketTask.onError(res => { console.log('WebSocket 连接失败', res) }) app.globalData.SocketTask.onMessage(msg => { app.globalData.Chatusers = JSON.parse(msg.data).len; }) }, gotochat(){ // 后台发请求 建立连接 // 携带user_id (此user_id 应为登陆后的user_id) this.webSocket(app.globalData.UserId); } }) ``` pages / chat / index.js ``` let config = require('../../utils/config.js') let app = getApp(); Page({ data: { socketMsg : '', // 发送消息 msg_data:[], //会话内容 }, // 进入页面获取 app.globalData.SocketTask onLoad(){ wx.setNavigationBarTitle({ title: '聊天室人数 / ' + app.globalData.Chatusers }) }, // 退出页面 断开socket 连接 onUnload(){ this.close_websocket(); }, onReady () { let { SocketTask } = app.globalData; SocketTask.onClose(onClose => { // console.log('监听 WebSocket 连接关闭事件。', onClose) this.close_websocket(); }) SocketTask.onError(onError => { // console.log('监听 WebSocket 错误。错误信息', onError) this.close_websocket(); }) SocketTask.onMessage(msg => { console.log('服务端数据返回:',msg) let { msg_data } = this.data; let { type } = JSON.parse(msg.data); // type 类型,message:普通消息,image:图片 , loginout:退出, loginin:进入 if (type == "message"){ let { nickname, message, fromId } = JSON.parse(msg.data); // 根据app.globalData.UserId(当前用户id)判断发消息人 let fromuser = 'other' if (fromId == app.globalData.UserId){ fromuser = 'me' } msg_data.push({ type, nickname, message, fromId, fromuser }) this.setData({ msg_data, }) } else if (type == "loginout" || type == "loginin"){ // 用户退出 / 进入 聊天室 app.globalData.Chatusers = JSON.parse(msg.data).len; wx.setNavigationBarTitle({ title: '聊天室人数 / ' + app.globalData.Chatusers }) } else if (type == "image" ){ // 图片上传服务器成功后 ws广播 let { msg_data } = this.data; let { src, type, fromId } = JSON.parse(msg.data); let fromuser = 'other' if (fromId == app.globalData.UserId) { fromuser = 'me' } msg_data.push({ type, src: `${config.httpAddress}/${src}`, fromId, fromuser, }) this.setData({ msg_data, }) } }) }, // 断开连接 close_websocket(){ let { SocketTask } = app.globalData; if (app.globalData.SocketTask){ SocketTask.close({ code: 1000, success: (res) => { console.log('关闭成功', res) app.globalData.SocketTask = null; }, fail: function (err) { console.log(err, "网络异常") }, complete: () => { console.log('完成') } }) } }, // 更改 inpiut value setstr(e){ this.setData({ socketMsg : e.detail.value }) }, // 发送消息 sendMsg(){ let { socketMsg } = this.data; let { SocketTask } = app.globalData; // 检测空字符 socketMsg = socketMsg.trim(); if (socketMsg.length == 0){ return; } SocketTask.send({ data: socketMsg, success: (res) => { // console.log('发送成功', res) this.setData({ socketMsg:'' }) }, fail: function (err) { console.log(err,"网络异常") }, }) }, // 图片上传 add_photo(){ let $this = this; wx.chooseImage({ success(res) { const tempFilePaths = res.tempFilePaths const uploadTask = wx.uploadFile({ url: `${config.httpAddress }/upfile/add`, // 图片上传接口地址 filePath: tempFilePaths[0], name: 'file', formData: { 'fromId': app.globalData.UserId }, success(res) { // console.log(res,"图片上传到服务器") } }) } }) } }); ``` ### node / app.js ``` let koa = require('koa') const staticFile = require('koa-static') let router = require('./router/upfile') let path = require('path') let url = require('url') let ws = require('ws') let socketServer = ws.Server let utils = require('./utils/utils') let app = new koa(); app.use(staticFile(path.join(__dirname + '/upload/'))) // 配置默认访问地址 let wss = new socketServer({port: 8080}); //创建websocketServer实例监听8080端口 let clientObj = require('./utils/setClients'); //创建客户端列表,用于保存客户端及相关连接信息 //监听连接 wss.on('connection', function(ws,req) { var parseObj = url.parse(req.url, true); clientObj.add({ "id": parseObj.query.id, "ws": ws, }) // 向前台发送聊天室用户信息 utils.openSocket(ws, parseObj.query.id) /*监听并广播消息*/ ws.on('message', function(message) { utils.broadcastSend(ws, "message", message, parseObj.query.id); }); /*监听断开连接*/ ws.on('close', function() { utils.closeSocket(ws, parseObj.query.id); }) }) app.use(router.routes()); app.listen(8090) ```