nodejs websocket上传大文件(Node.jsSocket.io实现一对一即时聊天)
nodejs websocket上传大文件(Node.jsSocket.io实现一对一即时聊天)
2024-09-21 06:51:27  作者:自述心情  网址:https://m.xinb2b.cn/know/pvf149267.html


作者:五月君

转发链接:https://mp.weixin.qq.com/s/TLKkRwftewa0uMvIRlOf5g

前言

实现一对一即时聊天应用,重要的一点就是消息能够实时的传递,一种方案就是熟知的使用 Websocket 协议,本文中我们使用 Node.js 中的一个框架 socket.io 来实现。

效果预览

先看下,我们实现的最终效果,如下所示:


你也可以在浏览器分别输入以下两个 URL 地址进行体验:

http://120.27.239.212:30010/?sender=赵敏&receiver=聂小倩http://120.27.239.212:30010/?sender=聂小倩&receiver=赵敏技术选型前端:HTML CSS JS 还用到了 Boostrap 来实现我们的页面布局和一些样式渲染。后端:Node.js express Socket.io。前端实现HTML 页面布局

聊天页面的 HTML 布局是不复杂的,大体分为 3 层,如下所示:

chat-header:聊天界面头部信息。chat-content:用来显示聊天的整体内容信息,现在看到的仅是一个空的 div 在发出或收到聊天信息之后会去操作 DOM 向聊天体内插入消息内容。chat-bottom:最下面展示了我们聊天窗口的内容输入窗口和发送按钮。

<divclass="container"><divclass="chat-headerrow"><spanclass="col-xs-2chat-header-leftglyphiconglyphicon-menu-left"></span><spanclass="col-xs-8chat-header-center"id="chatHeaderCenter"></span><spanclass="col-xs-2chat-header-rightglyphiconglyphicon-option-horizontal"></span></div><divclass="chat-content"id="chatContent"></div><divclass="chat-bottomrow"><spanclass="col-xs-10col-md-11input-text"><inputtype="text"class="form-control"id="inputText"placeholder="请输入要发送的内容..."></span><spanclass="col-xs-2col-md-1span-submit"><inputclass="btnbtn-defaultbtn-primaryinput-submit"id="sendBtn"data-dismiss="alert"type="submit"value="发送"></span></div></div><scriptsrc="/socket.io/socket.io.js"></script><scriptsrc="./js/chat.js"></script>

Socket.io Client

客户端首先创建一个 socket 对象,io() 的第一个参数是连接服务器的 URL,默认情况下是 window.location。Socket 的客户端和服务端都有两个函数 on()、emit() 这也是核心,通过这两个函数可以轻松的实现客户端与服务端的双向通信。

emit:触发一个事件,第一个参数是事件名称,第二个参数是要发送到另一端的数据,第三个参数是一个回调函数用来确认对方的接收信息,这个可以忽略。on:注册一个事件,用来监听 emit 触发的事件。

//js/chat.jsconstsocket=io();socket.on('connect',()=>{socket.emit('online',query.sender);});socket.on('reply_private_chat',replyPrivateMessage);...

在客户端发送消息,则是监听发送按钮的 onclick 事件或回车事件,对消息做一些处理通过 socket.emit 发送到服务端,由服务端转接到另一客户端。

前端部分更多细节代码,这里不再列举,可在 Github 上 Clone 下来自行查看,文末有代码示例地址。

constchatHeaderCenter=document.getElementById('chatHeaderCenter');constinputText=document.getElementById('inputText');constsendBtn=document.getElementById('sendBtn');chatHeaderCenter.innerText=query.receiver;sendBtn.onclick=sendMsg;inputText.onkeydown=sendMsgByEnter;functionsendMsg(){constvalue=inputText.value;if(!value)returnalert('Messageisrequired!');constmessage={sender:query.sender,receiver:query.receiver,text:value};socket.emit('private_chat',message,data=>{renderMessage(data,true);});inputText.value='';}...

后端实现使用 Express 搭建服务

使用 Express 搭建我们的后端服务,创建一个 app.js 里面监听 30010 端口,加载我们的客户端页面。

//app.jsconstexpress=require('express');constapp=express();constpath=require('path');constserver=require('http').createServer(app);constPORT=30010;app.use(express.static(path.join(__dirname,'../','public')));server.listen(PORT,()=>console.log(`Serverislisteningon${PORT}`));

引入 Socket.io

上面我们已经搭建了一个简单的 Express 服务,现在引入我们自定义的 io.js。

//app.jsrequire('./io.js')(server);

创建 io.js 在加载 socket.io 时传入 server 对象,这时会拿到一个服务端的 io 对象,同步的注册 connection 事件,如果有新的客户端进来会被触发,connection 回调函数的 socket 是指当前客户端与服务端建立的链接。

还有 online、private_chat、disconnect 这些事件有些是系统提供的,有些是我们自定义的,下文还会在介绍。

const_=require('underscore');constmoment=require('moment');constuserData=require('./users.json');constUSER_STATUS=['ONLINE','OFFLINE'];constusers={};module.exports=server=>{constio=require('socket.io')(server);io.on('connection',socket=>{socket.on('online',...)socket.on('private_chat',...);socket.on('disconnect',...);});}

上线通知

on('online') 是我们自定义的事件,由客户端上线后触发告诉我们当前客户端的用户信息,保存 socket.id 建立用户与 socket.id 的映射关系,用于后续私聊。这里的 socket.id 每一次客户端断开重链都是会变的。

socket.on('online',username=>{socket.username=username;users[username]={socketId:socket.id,status:USER_STATUS[0]};})

接收发送的私聊消息

on('private_chat') 也是我们自定义的事件,收到客户端发送的消息后对消息做处理,判断接收方是否在线,如果在线通过 socket.id 找到对应的 socket 向接收方推送消息,如果用户不在线,可以做些离线消息推送处理。这里私聊转发关键的一点是 socket.to().emit()。

socket.on('private_chat',(params,fn)=>{constreceiver=users[params.receiver];params.createTime=moment().format('YYYY-MM-DDHH:mm:ss');constsenderData=_.findWhere(userData,{username:params.sender});params.senderPhoto=(senderData||{}).photo;if(!params.senderPhoto){constsenderLen=params.sender.length;params.senderPhotoNickname=params.sender.substr(senderLen-2)}fn(params);if(receiver&&receiver.status===USER_STATUS[0]){socket.to(users[params.receiver].socketId).emit('reply_private_chat',params);}else{console.log(`${params.receiver}不在线`);//可以在做些离线消息推送处理}});

disconnect

断开链接时触发,reason 表示客户端或服务端断开链接的原因。在这个事件里我们也会更改断开链接的原因。

socket.on('disconnect',reason=>{if(users[socket.username])users[socket.username].status=USER_STATUS[1];});

代码&部署

我将以上示例打包为了一个 Docker 镜像,感兴趣的可以执行以下命令拉取,自行部署运行。

dockerpulldocker.io/qufei1993/private-chat-socketio

代码示例:

Github: https://github.com/qufei1993/Examples

Demo 在线体验:

http://120.27.239.212:30010/?sender=赵敏&receiver=聂小倩http://120.27.239.212:30010/?sender=聂小倩&receiver=赵敏总结

Socket.io 已经封装的很好了,使用它开发一个即时聊天应用更多工作需要我们去接入自己的业务逻辑,本文也只是一个聊天系统的冰山一角,还有很多需要去做,感兴趣的朋友欢迎关注,后续会持续分享一些其它功能。

推荐JavaScript学习相关文章

《JavaScript位运算最强指南 》

《JS正则表达式完整教程(一)「值得收藏」 》

《JS正则表达式完整教程(二)「值得收藏」 》

《用 80 行 Javascript 代码构建自己的语音助手 》

《玩转前端 Video 播放器 》

《纯JavaScript实现HTML5 Canvas 6种特效滤镜 》

《使用reveal.js制作精美的网页版PPT 》

《15个简单的JS编码标准让你的代码更整洁》

《Node 中的全链路式日志标记及处理》

《使用 Node 开发服务器项目时如何高效地打日志?》

《一文带你搞懂前端如何玩转 Word 文档》

《高频面试题:JavaScript事件循环机制解析》

《手写一个Promise/A 完美通过官方872个测试用例》

《你不知道的前端图片处理(上)》

《你不知道的前端图片处理(下)》

《钉钉前端-如何设计前端实时分析及报警系统》

《前端实现最佳截图方案(上)》

《前端实现最佳截图方案(下)》

《Node.js 实现抢票小工具&短信通知提醒(上)「干货」》

《Node.js 实现抢票小工具&短信通知提醒(下)「干货」》

《那些不常见,但却非常实用的JS知识点(上)》

《那些不常见,但却非常实用的JS知识点(下)》

《如何为团队定制自己的 Node.js 框架?》

《细品原生JS从初级到高级知识点汇总(一)》

《细品原生JS从初级到高级知识点汇总(二)》

《细品原生JS从初级到高级知识点汇总(三)》

《细品原生JS从初级到高级知识点汇总(四)》

《学习 jQuery 源码整体架构,打造属于自己的 js 类库》

《细说RTSP实现前端直播流探索记「干货」》

《一文带你搞懂前端登陆设计》

《使用 Node.js 将图片中的苹果变成橘子「实践」》

《基于Canvas实现的高斯模糊(上)「JS篇」》

《基于Canvas实现的高斯模糊(下)「JS篇」》

《由浅入深,66条JavaScript面试知识点(一)》

《由浅入深,66条JavaScript面试知识点(二)》

《由浅入深,66条JavaScript面试知识点(三)》

《由浅入深,66条JavaScript面试知识点(四)》

《由浅入深,66条JavaScript面试知识点(五)》

《由浅入深,66条JavaScript面试知识点(六)》

《由浅入深,66条JavaScript面试知识点(七)》

作者:五月君

转发链接:https://mp.weixin.qq.com/s/TLKkRwftewa0uMvIRlOf5g

  • 郭艾伦重回辽宁了吗(郭艾伦申请离开辽宁男篮)
  • 2024-09-21郭艾伦申请离开辽宁男篮郭艾伦申请离开辽宁男篮,放大10倍后看细节,原因清晰可见网友热议一针见血地指出:上赛季总决赛就能看出来,郭艾伦不满意,不想坐轮换休息,想在场上比赛,拿更多个人荣誉现在看看辽宁队是努力推翻,CBA顶薪锁。
  • 60岁娶小17岁娇妻如今老来得子(68岁34)
  • 2024-09-2168岁34今天要给大家讲到的这位老戏骨可以称得上是骨灰级的老戏骨,他就是演员金士杰这个名字印象不深,但你一定看过他演的戏,从近的来说,令我印象最深刻的就是金士杰在《楚乔传》里的精彩表现金士杰在《楚乔传》中饰演宇。
  • 原版兰亭序真迹有多大尺寸(天下第一行书兰亭序真迹在哪)
  • 2024-09-21天下第一行书兰亭序真迹在哪东晋永和九年(353年)三月初三,当时有一个传统习俗,在这天中人们需要去河边畅游一番,以消除不详之气这天,王羲之决定在兰亭(今浙江省绍兴市西南的兰渚山麓)组织一次集会,邀请谢安、孙绰等四十多位社会名流。
  • 肯尼亚定居(非洲肯尼亚生活工作经历分享-60)
  • 2024-09-21非洲肯尼亚生活工作经历分享-60随着中国开放的大门打开得越来越大,越来越多的中国人走了出去,也有越来越多的外国人走了进来我们会发现身边出现了越来越多的跨国婚姻,有嫁出去的,也有娶进来的;有在国内结婚的,也有在国外结婚的虽然跨国婚姻越。
  • 汽车底盘异响 解决方法(汽车底盘异响的原因有哪些)
  • 2024-09-21汽车底盘异响的原因有哪些随着汽车使用时间久了,底盘或多或少都有些异响,有些异响是属于底盘件正常的磨损导致的,有些异响则是零件损坏的警告,如果不尽快维修,会影响到行车安全螺栓松动造成底盘异响因底盘某个螺栓松动而出现的异响,原本。
  • 烤虾的腌制方法(烤虾的腌制方法简单介绍)
  • 2024-09-21烤虾的腌制方法简单介绍烤虾腌制方法一:(1)主料:对虾500克辅料:料酒25克、精盐适量、白糖30克、味精5克,花生油100克、香油25克、大料2克、葱段75克、姜片50克、清汤适量(2)做法:将对虾冲洗,减去虾须、虾腿,。
  • vivo x fold会降价么(三大升级值不值涨价千元)
  • 2024-09-21三大升级值不值涨价千元9月26日晚,vivo正式推出新一代折叠屏旗舰机vivoXFoldvivo产品副总裁黄韬表示,这是一款设计更、性能更、体验更的产品不过,相比于5个多月前的初代机型,vivoXFold的定价涨了1000。
  • 湛江适合游玩的地方(湛江这三个好玩的地方)
  • 2024-09-21湛江这三个好玩的地方湛江作为宜居城市为人们所熟知,上了魅力中国城之后,全国人民更是对湛江的旅游景点和文化特色向往不已一波又一波的游客从全国各地到湛江旅游,这三个地方成了游客们游玩的重要选择1、湖光岩湖光岩是中国有名的地质。
  • 三国名将怎么克制袁术(一手好牌却打得稀烂)
  • 2024-09-21一手好牌却打得稀烂袁术称帝后,先是被吕布打败,后又被曹操打败建安四年,袁术烧毁宫殿,前去投奔部下陈简、雷薄,却被陈简等拒绝,又想去青州投靠侄子袁谭,却被曹操派刘备拦截,袁术只好退到江亭此时正值盛夏,袁术想喝蜂蜜而不得,。
  • 这部电影见证了岁月是一把杀猪刀(蒙帕纳斯墓畔回忆)
  • 2024-09-21蒙帕纳斯墓畔回忆刚梳理过伊文思的电影人生,却蓦然记起,几年以前,我曾经去法国拜谒过这位“纪录电影之父”的墓地,而我却淡忘了,直到我发现了在伊文思墓地的留影那是2013年夏天,我与友人结伴去巴黎蒙帕纳斯墓地游历,偶然间。
  • 原神风岩神瞳位置高清图(原神岩神瞳位置图文介绍)
  • 2024-09-21原神岩神瞳位置图文介绍原神中,有很多的收集品,其中的各种瞳是非常贵重的东西,之前为大家说过风神瞳,这里来为大家介绍一下岩神瞳,游戏中岩神瞳是非常重要的收集品,那么,岩神瞳在哪里呢,本次就为大家带来了神岩神瞳详细位置汇总,也。
  • 婚礼敬茶改口主持词(婚礼敬茶改口主持词范文2篇)
  • 2024-09-21婚礼敬茶改口主持词范文2篇改口敬茶拜父母主持词一:新郎新娘喜结连理,两府结为秦晋之谊按着传统的习俗,二位新人要当众向父母敬茶改口请新娘向公公婆婆敬茶改口,甜甜的叫一声:爸爸妈妈请喝茶(新娘敬茶)请新郎向岳父岳母敬茶改口,同样叫。