赞
踩
首先是服务器端的实现,利用ws库
第一步,下载ws模块
npm i ws
第二步,粘贴代码
var express = require('express'); var router = express.Router(); var {addressBookModel} = require("../model/model/lzx") 导入ws模块 const WebSocket = require("ws"); let clients=[]; //存所有连接上的用户 // 创建WebSocket服务器 const wss = new WebSocket.Server({ port: 8080 }); // 监听连接建立事件 wss.on("connection", function(socket) { console.log("WebSocket连接已建立"); // 监听接收到客户端发送的消息 socket.on("message", function(message) { console.log("接收到户端发送的消息:" + message); //每个客户端都存上自己发来的phone做为唯一的id //连接上后就压进数组 clients.push({id:message,ws:socket}) }); // 监听连接关闭事件 socket.on("close", function() { console.log("WebSocket连接已关闭"); }); }); // 当有人发送消息的时候 router.post('/sendMsg', (req, res) =>{ //前端传过来的数据,otherId是当前要接受消息的人的id,message是消息主体,_id是当前发送消息的人的id,otherName是当前发送消息人的项目 let {otherId,message,_id,otherName} = req.body console.log(otherId); const datalist = { _id, message, otherName, } const Medatalist = { _id, message, } console.log(datalist); //循环遍历 找到你要发送的人 他的id 就发送 clients.forEach((ele) =>{ console.log('eleid',ele.id); console.log(otherId); if(otherId==ele.id){ ele.ws.send(JSON.stringify(datalist)); } }); //发送给自己客户端的数据 res.send(Medatalist) }) //获取我们的通讯录 router.get('/getAddressBooks',async function (req, res, next) { let {_id} = req.query let data = await addressBookModel.find({uid:_id}) res.send({ code:200, data }); }); module.exports = router;
然后是客户端的实现
第一步,配置网络权限
module.json5 { "name": "ohos.permission.INTERNET", },
注意!!!!文章中的this.id.slice(1,this.id.length-1)是给我们从首选项获取的数据进行了一次切割,因为我们首选存储后再读取出来可能会有多一个引号的问题,就例如""aaa"",也就是说全部都成了两个引号,所以需要切割
//引入鸿蒙官方的websocket模块 import webSocket from '@ohos.net.webSocket'; //映入鸿蒙官方的通知模块,就是一发消息,我们的手机上通知的那个模块 import NotificationManager from '@ohos.notificationManager'; //引入axios import axios from '../../http/index' //引入路由 import router from '@ohos.router'; //引入首选项存储,这里我是利用首选项存储了我们当前用户的id,用户名,头像等 import SharePre from '../../util/SharePre' //引入鸿蒙官方提供的文件管理,用来存储聊天记录 import common from '@ohos.app.ability.common'; //文件操作模块 import fs from '@ohos.file.fs'; @Entry @Component struct Chat{ //读取上级传来的params,这里我的params中是要聊天的那个人的信息 @State params:any = router.getParams() @State msg:string = "" @State username:string = "" @State _id:string = "" @State imgPath:string = "" //存储聊天记录 @State chatRecords:Array<{_id:string,message:string}> = [] //获取上下文,用于存储聊天记录 private context = getContext(this) as common.UIAbilityContext //声明一个ws,用于websocket的使用 private ws async aboutToAppear(){ //获取首选项存储的id,用户名和头像 this._id = await SharePre.getPreferenceValue('MyPreferences','_id','666') as string this.username = await SharePre.getPreferenceValue('MyPreferences','username','666') as string this.imgPath = await SharePre.getPreferenceValue('MyPreferences','imgPath','666') as string //读取聊天记录,从我们存储的聊天记录文件中获取聊天记录 let file = fs.openSync(this.context.filesDir+`/${this.params._id}.txt`,fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) let buf = new ArrayBuffer(2048) let leng = fs.readSync(file.fd,buf,{offset:0}) this.chatRecords = JSON.parse(String.fromCharCode.apply(null,new Uint8Array(buf.slice(0,leng)))) fs.closeSync(file) //创建websocket连接 this.ws = webSocket.createWebSocket() this.ws.connect("ws://59.110.165.22:8080") this.ws.on("open",(err,value)=>{ if(!err){ console.log("连接成功") //在这里直接先像服务器发送一次请求,先发送一次请求是为了将id添加到后端的用户列表中 this.ws.send(this._id.slice(1,this._id.length-1)) } }) this.ws.on("message",(err,value)=>{ if(!err){ console.log("收到消息"+value) this.chatRecords.push(JSON.parse(value)) //这里打印的是我们聊天记录的存储位置 console.log("我是涛的文件",this.context.filesDir) //存储聊天记录 let file = fs.openSync(this.context.filesDir+`/${this.params._id}.txt`,fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) fs.write(file.fd,JSON.stringify(this.chatRecords)) fs.close(file) //收到消息时通知 let notificationRequest = { id: 1, content: { contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT, // 普通文本类型通知 normal: { title: JSON.parse(value).otherName, text: JSON.parse(value).message, } } } NotificationManager.publish(notificationRequest, (err) => { if (err) { console.error(`[ANS] failed to publish, error[${err}]`); return; } console.info(`[ANS] publish success`); }); } }) this.ws.on("close",(err,value)=>{ if(!err){ console.log("连接断开") } }) } async sendData(){ console.log('params_id',this.params._id) try { //给后端发送请求,发送数据 const response = await axios.post("lzx/sendMsg",{otherId:this.params._id,message:this.msg,_id:this._id.slice(1,this._id.length-1),otherName:this.username.slice(1,this.username.length-1)}); console.log(JSON.stringify(response)); this.chatRecords.push({"_id":this._id.slice(1,this._id.length-1),message:response.data.message}) //这里打印的是我们聊天记录的存储位置 console.log("我是涛的文件",this.context.filesDir) //存储聊天记录 let file = fs.openSync(this.context.filesDir+`/${this.params._id}.txt`,fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE) fs.write(file.fd,JSON.stringify(this.chatRecords)) fs.close(file) //发送后清空聊天数据 this.msg = "" } catch (error) { console.error(JSON.stringify(error)); } } @Builder popupBuilder() { Row({ space: 2 }) { Image($r("app.media.icon")).width(24).height(24).margin({ left: 5 }) Text('This is Custom Popup').fontSize(15) }.width(200).height(50).padding(5) } @Builder Title(){ Row(){ Text(this.params.username) NavRouter(){ Text("...") //这里我们做了一个跳转的操作,跳转到我们对方的详细信息页面,对于聊天没有帮助,可以不看 .onClick(()=>{ router.pushUrl( { url:"pages/MyMessage/ChatSettings", params:this.params } ) }) } }.width("90%").justifyContent(FlexAlign.SpaceAround) } build(){ Navigation() { Column(){ Column(){ List({space:10}){ ForEach(this.chatRecords,(item)=>{ ListItem(){ if(item._id==this._id.slice(1,this._id.length-1)){ Row(){ Row(){ Text(item.message) } .width(150) .height(50) .backgroundColor("#FFB6C1") .borderRadius(15) Text(":") //使用时需要进行切片,因为默认会多加一层引号,如果不切片,出不来效果 Image(this.imgPath.slice(1,this.imgPath.length-1)) .width(50) .height(50) .borderRadius(50) } .width("100%") .justifyContent(FlexAlign.End) }else if(item._id==this.params._id){ Row(){ Image(this.params.imgPath) .width(50) .height(50) .borderRadius(50) .onClick(()=>{ router.pushUrl( { url:"pages/MyMessage/ChatSettings", params:this.params } ) }) Text(":") Row(){ Text(item.message) } .width(150) .height(50) .backgroundColor("#FFF") .borderRadius(15) } .width("100%") } } }) }.width("100%").height("100%").backgroundColor("#eee") } .width("100%") .height("93%") Row(){ TextInput({placeholder:"请输入您想要发送的内容",text:this.msg}) .width("80%") .height(50) .onChange((e)=>{ this.msg = e }) Button("发送") .height(50) .width(70) //发送消息 .onClick(()=>{ this.sendData() }) } .width("100%") } .width('100%') .height('100%') .justifyContent(FlexAlign.SpaceBetween) } .title(this.Title()) .titleMode(NavigationTitleMode.Mini) } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。