教你从零开始用WebSocket打造一个IM聊天室
之前我们在 IM即时聊天室(一):WebSocket 和 IM即时聊天室(二): Socket.io + Node.js
两篇文章中介绍了搭建一个IM的所需的技术栈和通信原理。那在这篇文章里我们就来详细说一下具体的应用并提供完整源码。
个人Blog地址:IM即时聊天室(三):项目详解及源码分析
聊天室在线地址:点此进入
PS: 这是我网络编程课的一个小作业,因为博主比较懒所以这篇文章的大部分由我的课程报告组成(逃)
实现目标
应用实例是一个多人聊天室程序,用户可以通过指定服务器IP进入聊天室和聊天室内其他用户进行聊天,聊天室的功能主要有文本、表情和图片传输,并在Web界面中显示。
需求分析
应用采用客户/服务器模式,分为客户端程序和服务器端程序。
用户通过客户端可以选择头像,发送信息、表情、图片
服务端可以同时接收多个客户端信息,并根据需求进行转发、广播或者回传给客户端特定的消息。
客户端程序和服务器程序通过网络交换聊天的字符串内容(其中表情和头像为特殊格式代码,图片为转码后获得的URL格式)
话不多说,先看程序效果展示:
技术实现
通信协议选择
Balabalabala… 详见下面两篇文章
IM即时聊天室(一):WebSocket
IM即时聊天室(二):Socket.io + Node.js客户端
UI界面:HTML+CSS+Bootstrap自适应
界面交互:原生Javascript+jQuery
消息的发送和接收:Socket.io
PS:由于客户端代码太太太太太多了,我只挑比较有特点的的讲一下
登录啥的就不讲了,大概思路就是开始时隐藏聊天界面,登录成功后隐藏登录界面显出聊天界面,源码里有完整的注释
先贴一下客户端代码大致结构图:
比较有意思的代码是我仿照微信做了一个回到最新消息处的功能。
当我们在聊天时,我们会希望最新的消息实时显示出来,但是当我们在看历史消息时,可不希望被强行定位到最新消息处。并且在查看历史消息时,可以通过按钮回到最新消息处。
于是我们就要判断用户在查看历史消息还是正在聊天,方法就是判断最新的消息是否出现在了用户窗口里。
关键代码:
```
/*将页面下拉到最新消息处*/function scrollToEnd(){var div = document.getElementsByTagName("div");div_length = div.length-4;div[div_length].scrollIntoView({behavior: "smooth"}); //平滑滚动,提高了用户体验}/*判断当有新信息来时,用户是否在页面底端*/function isNewInWindow(){var div = document.getElementsByTagName("div");div_length = div.length-5;if(isInWindow(div[div_length])){return true;}return false;}/*判定元素是否在界面内*/function isInWindow(x){ if(x.getBoundingClientRect().top > window.innerHeight){console.log("down");return false;}else if(x.getBoundingClientRect().bottom < 0){console.log("up");return false;}return true;}
```
- 服务端
服务端主要使用了Node.js+Socket.io来构建服务端,需要Node环境来运行。
主要的思路:请求HTTP服务 → 在此基础上使用WebSocket → 引入Socket.io模块并创建实例 → 用该实例进行socket监听 → 通过socket进行消息的发送、转发、群发等。
服务端关键代码:
```
var app = require('http').createServer();
var io = require('socket.io')(app);
var PORT = 8081;
/*定义用户数组*/
var users = [];
app.listen(PORT);io.on('connection',function (socket) { //监听//发送、转发、群发消息
})
```
- 图片文件传输
图片传输部分我本来是想用Base64编码,先在客户端读取图片二进制信息并编成Base64格式发送给服务端,服务端转发后别的客户端接收后解码。
但是后面放弃了这一方式,因为直接传输二进制信息太慢了,于是改用了HTML5的Filereader方法。
这个方法有个优点就是其中的readAsDataURL函数可以直接将图片二进制信息转成URL格式,这样子我只用发送并转发一个简短的URL,客户端直接根据URL加载图片,省去了大量传输和解码时间。
关键代码:
```
//图片发送
document.getElementById(‘sendImage’).addEventListener(‘change’,
function() {
//检查是否有文件被选中
if (this.files.length != 0) {
//获取文件并用FileReader进行读取
var file = this.files[0],
reader = new FileReader();
if (!reader) return;reader.onload = function(e) {//读取成功,发送到服务器socket.emit('sendImg',{username:uname,image: e.target.result,date:new Date().toTimeString().substr(0, 8),headnum:headnum});};reader.readAsDataURL(file);};
}, false);```
- 头像选择/表情包传输
头像和表情已经预先放置在客户端中,用户在选择以后将产生特定格式的代码,放置到要发送的信息当中。
别的客户端接收到的消息时候,先用正则表达式检索信息中是否存在该格式代码,若有则加载相应的头像/表情,以达到效果。
关键代码,以表情为例:
//emoji
document.getElementById('emojiWrapper').addEventListener('click',
function(e) {//获取被点击的对象var target = e.target;console.log(target);if (target.nodeName.toLowerCase() == 'img') { //如果是表情图像则发送var sendtxt = document.getElementById('sendtxt');sendtxt.focus();sendtxt.value = sendtxt.value + '[emoji:' + target.num + ']';};
}, false);
源码
Gitbub地址:https://github.com/KMKNKK/Chatroom-WebSocket/tree/homework
(欢迎fork和star)
重要文件结构:
│
├─index.html //客户端
│
├─css
│ bg.jpg //背景图
│ chat.css
│
├─images //图片资源
│ │ logo.png
│ │ toNewMessage.png
│ │
│ ├─emoji //表情
│ │
│ └─user //头像
│
│
├─js
│ │ app.js //服务端JS
│ │ chat.js //客户端JS
│ │ jquery.min.js //依赖
│ │ socket.io.js //依赖
│ │
│ └─.vscode
│ settings.json
│
├─new //BootStrap和jQuery文件
│ │ jquery-3.2.1.min.js
│ │
│ └─bootstrap-3.3.7-dist
│
│
└─node_modules //依赖文件
教你从零开始用WebSocket打造一个IM聊天室相关推荐
- Vue全家桶+Socket.io+Koa2打造一个智能聊天室 接口已开放
Vue.js+Socket.io+Koa2打造一个智能聊天室 Vue.js全家桶+Socket.io+Express/Koa2 打造的一个智能聊天室. 已经开源啦!为了方便大家学习,智能机器人.IP定 ...
- 如何打造一个语音聊天室
语音聊天室这个名词可能有点陌生,实际上相关的产品还是很多的,例如游戏里的开黑语音.在线课堂等.语音聊天室可以认为视频直播的前身,很多音视频平台的架构是从语音聊天室演进为视频直播室的.本文主要介绍语音聊 ...
- 实战 | 使用 Python 开发一个在线聊天室
点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 云想衣裳花想容,春风拂槛露华浓. ...
- vue php聊天室,Laravel + Swoole 打造IM简易聊天室
Laravel + Swoole 打造IM简易聊天室 最近在学习Swoole,利用Swoole扩展让PHP生动了不少,本篇就来Swoole开发一款简易的IM聊天室 应用场景:实现简单的即时消息聊天室. ...
- 连夜撸了一个简易聊天室
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 分不清轮询.长轮询?不知道什么时候该用websocket还 ...
- rudesocket如何使用_[WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebS...
前言 本文中搭建了一个简易的多人聊天室,使用了WebSocket的基础特性. 源代码来自老外的一篇好文: 本文内容摘要: 初步理解WebSocket的前后端交互逻辑 手把手使用 SpringBoot ...
- 撸一个简易聊天室,不信你学不会实时消息推送(附源码)
点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:推荐 19 个 github 超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多 分不清轮询.长轮询? ...
- SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室
SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室 一.概述 WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 ...
- 实战|使用 Python 开发一个在线聊天室
「来源: |Python爬虫与数据挖掘 ID:crawler_python」 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 云想衣裳花想容,春风拂槛露 ...
最新文章
- codevs1137 计算系数
- Jenkins在Mac平台安裝
- 单片机彩灯移动实验_单片机课程设计彩灯实验.doc
- 线上活动 | 2020年PM如何提高求职成功率?
- 不用数组 java输出杨辉三角_不用数组实现杨辉三角(巴斯卡三角形)
- 第一个c++泛型函数(即模板)
- 前端学习(1186):双向数据绑定
- 攻克学习多线程时碰到的难题(zz)
- 编程实战:如何管理代码里的常量
- ContainerAllocator详解
- C++ 深拷贝和浅拷贝std::move移动构造函数,移动赋值函数
- SQL Sever 数据完整性
- android room 简书,android Room库使用问题
- Airflow调度 Design
- 算POTCAR要上心!
- 销售额高达2.8亿的 “像素猫头鹰”项目Moonbirds,何以令NFT收藏家趋之若鹜?
- c语言socket通讯和进行进行大文件分片传输
- UVa 11437 (梅涅劳斯定理) Triangle Fun
- 一步一步使用ABP框架搭建正式项目系列教程之本地化详解
- 微信集成监控Job状态的功能