之前我们在 IM即时聊天室(一):WebSocket 和 IM即时聊天室(二): Socket.io + Node.js
两篇文章中介绍了搭建一个IM的所需的技术栈和通信原理。那在这篇文章里我们就来详细说一下具体的应用并提供完整源码。
个人Blog地址:IM即时聊天室(三):项目详解及源码分析

聊天室在线地址:点此进入


PS: 这是我网络编程课的一个小作业,因为博主比较懒所以这篇文章的大部分由我的课程报告组成(逃)


实现目标

应用实例是一个多人聊天室程序,用户可以通过指定服务器IP进入聊天室和聊天室内其他用户进行聊天,聊天室的功能主要有文本、表情和图片传输,并在Web界面中显示。

需求分析

  1. 应用采用客户/服务器模式,分为客户端程序和服务器端程序。

  2. 用户通过客户端可以选择头像,发送信息、表情、图片

  3. 服务端可以同时接收多个客户端信息,并根据需求进行转发、广播或者回传给客户端特定的消息。

  4. 客户端程序和服务器程序通过网络交换聊天的字符串内容(其中表情和头像为特殊格式代码,图片为转码后获得的URL格式)

话不多说,先看程序效果展示:

技术实现

  1. 通信协议选择
    Balabalabala… 详见下面两篇文章
    IM即时聊天室(一):WebSocket
    IM即时聊天室(二):Socket.io + Node.js

  2. 客户端
    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;}
```
  1. 服务端
    服务端主要使用了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) { //监听//发送、转发、群发消息
})
```
  1. 图片文件传输

图片传输部分我本来是想用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);```
  1. 头像选择/表情包传输
    头像和表情已经预先放置在客户端中,用户在选择以后将产生特定格式的代码,放置到要发送的信息当中。

别的客户端接收到的消息时候,先用正则表达式检索信息中是否存在该格式代码,若有则加载相应的头像/表情,以达到效果。

关键代码,以表情为例:

//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聊天室相关推荐

  1. Vue全家桶+Socket.io+Koa2打造一个智能聊天室 接口已开放

    Vue.js+Socket.io+Koa2打造一个智能聊天室 Vue.js全家桶+Socket.io+Express/Koa2 打造的一个智能聊天室. 已经开源啦!为了方便大家学习,智能机器人.IP定 ...

  2. 如何打造一个语音聊天室

    语音聊天室这个名词可能有点陌生,实际上相关的产品还是很多的,例如游戏里的开黑语音.在线课堂等.语音聊天室可以认为视频直播的前身,很多音视频平台的架构是从语音聊天室演进为视频直播室的.本文主要介绍语音聊 ...

  3. 实战 | 使用 Python 开发一个在线聊天室

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 云想衣裳花想容,春风拂槛露华浓. ...

  4. vue php聊天室,Laravel + Swoole 打造IM简易聊天室

    Laravel + Swoole 打造IM简易聊天室 最近在学习Swoole,利用Swoole扩展让PHP生动了不少,本篇就来Swoole开发一款简易的IM聊天室 应用场景:实现简单的即时消息聊天室. ...

  5. 连夜撸了一个简易聊天室

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 分不清轮询.长轮询?不知道什么时候该用websocket还 ...

  6. rudesocket如何使用_[WebSocket入门]手把手搭建WebSocket多人在线聊天室(SpringBoot+WebS...

    前言 本文中搭建了一个简易的多人聊天室,使用了WebSocket的基础特性. 源代码来自老外的一篇好文: 本文内容摘要: 初步理解WebSocket的前后端交互逻辑 手把手使用 SpringBoot ...

  7. 撸一个简易聊天室,不信你学不会实时消息推送(附源码)

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:推荐 19 个 github 超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多 分不清轮询.长轮询? ...

  8. SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室

    SpringBoot入门建站全系列(二十七)WebSocket做简单的聊天室 一.概述 WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 ...

  9. 实战|使用 Python 开发一个在线聊天室

    「来源: |Python爬虫与数据挖掘 ID:crawler_python」 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 云想衣裳花想容,春风拂槛露 ...

最新文章

  1. codevs1137 计算系数
  2. Jenkins在Mac平台安裝
  3. 单片机彩灯移动实验_单片机课程设计彩灯实验.doc
  4. 线上活动 | 2020年PM如何提高求职成功率?
  5. 不用数组 java输出杨辉三角_不用数组实现杨辉三角(巴斯卡三角形)
  6. 第一个c++泛型函数(即模板)
  7. 前端学习(1186):双向数据绑定
  8. 攻克学习多线程时碰到的难题(zz)
  9. 编程实战:如何管理代码里的常量
  10. ContainerAllocator详解
  11. C++ 深拷贝和浅拷贝std::move移动构造函数,移动赋值函数
  12. SQL Sever 数据完整性
  13. android room 简书,android Room库使用问题
  14. Airflow调度 Design
  15. 算POTCAR要上心!
  16. 销售额高达2.8亿的 “像素猫头鹰”项目Moonbirds,何以令NFT收藏家趋之若鹜?
  17. c语言socket通讯和进行进行大文件分片传输
  18. UVa 11437 (梅涅劳斯定理) Triangle Fun
  19. 一步一步使用ABP框架搭建正式项目系列教程之本地化详解
  20. 微信集成监控Job状态的功能

热门文章

  1. k-means 的原理,优缺点以及改进
  2. 港股中的老千,千万别碰!
  3. 学习KNN算法重点目标
  4. iOS应用架构谈 网络层设计方案--RTNetworking
  5. MySQL 正负数排序
  6. 粉象生活优惠券项目优势
  7. 关于手机唯一识别码的研究meid和imei
  8. ffmpeg之av_read_frame
  9. 宝贝快出生的这三个表现,孕妈尽快去医院待产
  10. TMS320F2837x开发例程使用手册