入门级node+uni-app开发即时通讯聊天室(6)一对一用户聊天的实现(三)

前言: 这篇是核心实现,如果你感觉到某些地方的写法有些让你感觉到迷惑,请你暂时先忽略(我一开始也感觉十分困难),先把他做出来,不要太纠结于为什么,当然,我仍然会尽我的能力用代码和文字将他表示清楚。这是来自我自学的经验之谈,当你实在难以理解,先放下它。此篇将会介绍socket.io的使用,最主要的是要搞明白客户端与服务器端之间的数据流动,假如你对数据的流动完全清晰可见,这个篇章也许对你不是难题。我实现的即时通讯是基于socket.io的,毫无疑问。

首先我们先介绍socket.io,它是由WebSocket封装而来的。

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

这是官方对于websocket的介绍,关注点应该在持久性的连接并进行双向数据传输上。这个应该如何理解呢?双向数据传输,就是服务器端可以发送数据到客户端,客户端也可以发送数据到服务器端。这样的话理解不太顺畅,这样的话TCP连接不也一样吗,它同样能够做到?他们的区别在于TCP都是通过客户端请求数据,服务端再返送给客户端需要的数据。但假设我们代入场景,我们的聊天当对方发送消息的时候,我们需要能够’即时‘的接收到对方发出的消息,而这个时候我们还得去请求服务器端最新的消息,问题就来了,我们该如何确定何时该请求?
顺理成章的,我们能想到的最好的做法是当服务器端接受到新消息的时候,把这个消息进行’广播‘,告诉所有人,我的消息已经更新了,你们需要再请求一次。这就是websocket在即时通讯这方面的优越之处,当客户端与服务器端建立连接之后,它不必等待客户端的请求,可以推送数据给客户端进行处理。这种方式也是所谓的订阅者模式。

有了以上的知识后我们尝试去使用它。
首先得安装socket.io 官网地址是https://socket.io/

cnpm install socket.io --save

安装好之后在根目录下建造一个socket目录存放socket.js 这个文件用于管理我们的socket.io。

接着,现在把它找到,然后把这个文件放在我们的前端common/js下。
在这里插入图片描述
在这里插入图片描述
照着它的官网示例,我们的后端代码
在这里插入图片描述
在这里插入图片描述
我们想在另一个文件中处理还得把这个io传进去。
在这里插入图片描述

在这里插入图片描述
后端的基础配置就好了,我们到前端试试看能否正常连接。
在这里插入图片描述

Vue.prototype.$socket = io('ws://192.168.96.36:3000',{transports: ['websocket']})

注意 这里,你最好先别填localhost,因为后面我们需要使用手机模拟器去测试我们是否能正常的实时通讯。找到你自己的IP地址填上,别嫌麻烦。
如果你正常按着步骤来,到这里的时候你的后端应该已经能打印连接成功了,第一步我们就成功了,这证明了我们的工具已经能正常的使用,接着就到我们处理自己项目的逻辑了。

我们设想一下,当我们进入聊天页面会发生什么?将当前未读的消息更新为1,表示我们已经读取了当前朋友发送给我们的消息。
在这里详细的说明msg_status 消息的状态:
msg_status为0时,说明这个消息对于接收方是未读的。
msg_status为1时,说明这个消息对于接收方是已读的。
当然,当我们发出消息的时候这个消息对我们默认是已读的,msg_status对我们作为发送方是没有任何的意义的。(我曾经脑子混乱陷入了死胡同,想了很多种状态表示才意识到。)理解这个很重要,以免你产生某种形式上的认知错误。
同时我们还得关注到一点,假设我们两个都连接到了socket,处在同一个房间(暂时不必记住)下,此时我们对于对方发出的消息应该是已读的,如何界定这个msg_status它插入的时候应该是0或者1?(这里我们应该避免每一次都对msg_status进行更新,只需在第一次进入房间的时候更新未读消息的状态)
假如你对数据的流向清晰可见,那么你应该会有一个显而易见的方法,通过在socket.io的内部定义一个全局变量,用于保存当前的一对一的聊天的用户,判断当前的用户是否存在在当前的房间里。如果是,我们发出的消息的状态msg_status就是1,否则就是0。当用户点击返回,退出了当前这个房间时,我们告诉对方用户已经退出,改变msg_status的插入状态。

后端
1.更新消息状态

有了初步的想法我们可以开始写代码了。现在我们去实现的是当进入这个房间的时候更新当前的消息为已读,十分简单。当我们应用在运行的时候,websocket就已经连接上了。
在这里插入图片描述

在这里插入图片描述
这里如果你对vue的组件传值有过学习的话就不必多去想,就是你一开始直接认为的意思。否则:on表示监听一个’readOneToOneMessage’的事件,同时执行一个自定义的回调函数。emit表示发送一个事件,传入参数。
前端只用将他在onload生命周期里发送事件就行。

2.修改上个小章节的BUG

在这里插入图片描述
同时修改上一个小章节的bug,这个bug的产生原因是他始终取前10条数据,当互相的数据量超过10条的时候只能显示最上面的10条数据。而我们需要的应该是‘最近的’的10条。所以不可避免的前端我们需要reverse一下渲染数组。

3.发送消息与接受消息

在这里插入图片描述

进来的时候生成一个在连接中的用户列表,通过这个唯一的用户名作为键值去确定唯一的一个ID,这个socket.id是由socket.io自己进行分配的唯一ID。

在这里插入图片描述
详细说一下为什么这么写,我们前端可以直接通过构造一个消息对象直接推入数组,不必到服务端再进行处理,到服务端处理的应该是将这个消息对象进行推送给别的客户端进行渲染,推送给谁?这就是我们为什么保存一个用户列表的原因。

前端
1.接受消息

在这里插入图片描述
直接onload生命周期里将他执行。

2.发送消息

在这里插入图片描述

额。好像有点多,但别害怕,让我抽丝剥茧给你说明。
使用v-model输入框绑定了chatmsg

  • 1.首先我们简单的判断下,如果是输入框是空的就不让他发送了。
  • 2.接着构造插入数据库的消息对象,这个消息对象与我们的渲染对象是不同的,这个需要注意到。
  • 3.供自己使用的渲染对象,与让对方使用的渲染数组,其实他们的主要区别就是渲染的地方。
  • 4.发送完消息后自动让他滚动到最底部区域。
    在这里插入图片描述
    别问我为什么要使用异步,我也不知道,但他就是这么写才能跑通。
3.用户连接

在这里插入图片描述
放于index页面,表示进来的时候,就在socket里保存该用户。

测试

我使用的是雷电模拟器,如果你还未安装过任何模拟器可以直接上官网搜索雷电模拟器去下载。接着开启开发者选项
方法如下:找到设置
在这里插入图片描述
在这里插入图片描述
单机版本号5次就可以开启了。
接着进入开发者选项,找到
在这里插入图片描述
准备工作完成了,再次声明,socket连接的地址与接口的地址请使用自己的ip地址如下面Network中的所示
在这里插入图片描述
在这里插入图片描述
运行到手机或模拟器 点击第一个选项就可。如果选项未有,查看自己的usb调试接口开启了没有。雷电模拟器打开了没有。

测试我们的功能是否能实现。
OK,当你进去的时候你会发现连接始终只有一个,模拟器端的始终连接不上。如下图所示
在这里插入图片描述在这里插入图片描述
点击开启调试服务。不然socket.io是不能正常连接的。
在这里插入图片描述
首先先测试消息状态是否能正常修改。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
当我们进入这个页面的时候,数据库修改成已读了。当然现在你返回查看效果肯定是不能显示的,因为我们还没处理这些相关的逻辑。

再到消息的测试。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这里的头像为什么显示不出来?很简单,因为我们数据库里的引用是localhost,但是我们在h5端的localhost与在模拟器的localhost很显然是不同的。

至此其实一个简易的核心实现就已经完成了。但是不要满足,细细想下这个体验其实极其糟糕,如果你足够细心你就会发现,当你返回的时候消息跟提示并没有变化,同时我们插入数据库的msg_status应该是动态判断的,假如我们两个都已经在这一个房间里的,此时不论是谁发出去的都应该是已读的状态。所以我们下个小章节还没到图片视频等等这些东西,事实上通过封装的API能实现的东西不算太有难度,我更建议你细细的去品味我说的,学习好socket.io的使用,清晰的了解数据流向,根据这个流向去思考生成一个解决方案,并通过代码实现它更有意义。

闲话:回到家里蹲的日子,活脱脱一条咸鱼,玩了好多天,最近才得以静下心来写这篇博客,这也不是一下子能完成的事,如果我写出的代码跟我第一次写的并无两样,纯粹是垃圾堆积那我写博客的意义就不在了,我是希望假如你不及我,你能从这篇博客里获取到一种还算可以的思考的方式,

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值