express+websocket实现线上聊天

2023-11-05

1.webSocket简介

WebSocket是一种通信协议,可在单个TCP连接上进行全双工通信。WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输

  • WebSocket是HTML5下一种新的协议(websocket协议本质上是一个基于tcp的协议)
  • Websocket是一个持久化的协议

2.websocket的原理 

  1. websocket约定了一个通信的规范,通过一个握手的机制,客户端和服务器之间能建立一个类似tcp的连接,从而方便它们之间的通信
  2. 在websocket出现之前,web交互一般是基于http协议的短连接或者长连接
  3. websocket是一种全新的协议,不属于http无状态协议,协议名为"ws"

3.websocket和http的区别?

相同点:

  1. 都是基于tcp的,都是可靠性传输协议
  2. 都是应用层协议

不同点:

  1. WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息
  2. HTTP是单向的
  3. WebSocket是需要浏览器和服务器握手进行建立连接的
  4. 而http是浏览器发起向服务器的连接,服务器预先并不知道这个连接

两者之间的一个联系

WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的

4. websocket的改进

一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。在客户端断开WebSocket连接或Server端中断连接前,不需要客户端和服务端重新发起连接请求。在海量并发及客户端与服务器交互负载流量大的情况下,极大的节省了网络带宽资源的消耗,有明显的性能优势,且客户端发送和接受消息是在同一个持久连接上发起,实现了“真·长链接”,实时性优势明显

 

5. websocket解决的问题

1.http存在的问题

  • http是一种无状态协议,每当一次会话完成后,服务端都不知道下一次的客户端是谁,需要每次知道对方是谁,才进行相应的响应,因此本身对于实时通讯就是一种极大的障碍
  • http协议采用一次请求,一次响应,每次请求和响应就携带有大量的header头,对于实时通讯来说,解析请求头也是需要一定的时间,因此,效率也更低下
  • 最重要的是,需要客户端主动发,服务端被动发,也就是一次请求,一次响应,不能实现主动发送

2.long poll(长轮询)

  • 对于以上情况就出现了http解决的第一个方法——长轮询
  • 基于http的特性,简单点说,就是客户端发起长轮询,如果服务端的数据没有发生变更,会 hold 住请求,直到服务端的数据发生变化,或者等待一定时间超时才会返回。返回后,客户端又会立即再次发起下一次长轮询
  • 优点是解决了http不能实时更新的弊端,因为这个时间很短,发起请求即处理请求返回响应,实现了“伪·长连接”

3.Ajax轮询

  • 基于http的特性,简单点说,就是规定每隔一段时间就由客户端发起一次请求,查询有没有新消息,如果有,就返回,如果没有等待相同的时间间隔再次询问
  • 优点是解决了http不能实时更新的弊端,因为这个时间很短,发起请求即处理请求返回响应,把这个过程放大n倍,本质上还是request = response

  代码展示

 下载

npm i express-ws

app.js

var ws = require('express-ws')


var app = express();
ws(app)


app.listen('8888')

index.js

var express = require('express');
var router = express.Router();
var ws = require('express-ws')
ws(router)
const wss = []
router.ws("/",(ws,req)=>{
  // console.log("连接成功!");
  // send给客户端发消息
  // on是监听事件
  // message表示服务端传来的数据
  wss.push(ws)
  ws.on("message", (msg) => {
    console.log(msg);
      // 给所有的客户端广播消息
      // console.log(msg);
      // console.log(wss);
      wss.forEach((e) => {
          e.send(msg)
      })
  })
  // close 事件表示客户端断开连接时执行的回调函数
ws.on('close', function (e) {
  console.log('close connection')
})

})
module.exports = router;

html页面(根目录创建)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <input type="text" name="msg" id="msg">
    <input type="button" value="发送" id="btn">
    <ul id="showMsg"></ul>
    <script>
        function UrlSearch() {
            var name, value;
            var str = location.href; //取得整个地址栏
            var num = str.indexOf("?")
            str = str.substr(num + 1); //取得所有参数 stringvar.substr(start [,length ]
            var arr = str.split("&"); //各个参数放到数组里
            for (var i = 0; i < arr.length; i++) {
                num = arr[i].indexOf("=");
                if (num > 0) {
                    name = arr[i].substring(0, num);
                    value = arr[i].substr(num + 1);
                    this[name] = value;
                }
            }
        }
        var Request = new UrlSearch(); //实例化
        var ws = new WebSocket("ws://localhost:8888");
        var btn = document.getElementById('btn')
        var inputDom = document.getElementById('msg')
        var ulDom = document.getElementById('showMsg')
        btn.addEventListener('click', function () {
            ws.send(inputDom.value)
            inputDom.value = ''
        })
        ws.onopen = function (evt) {
            console.log("Connection open ...");
            //ws.send("Hello WebSockets!");
        };
        let liHtml = ''
        ws.onmessage = function (evt) {
            console.log(evt.data);
            liHtml += `<li>:${evt.data}</li>`
            ulDom.innerHTML = liHtml
        };
        ws.onclose = function (evt) {
            console.log("Connection closed.");
        };
    </script>
</body>
</html>

在浏览器中同时打开两个html页面

另一个页面

后端打印

这样一个简单的在线聊天就完成了,这是多聊,还可以实现单聊模式 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

express+websocket实现线上聊天 的相关文章

随机推荐

  • KyLin的网页界面使用

    1 美图 上一篇 http blog csdn net qq 21383435 article details 75198823 1 根据上一张分析的内容得知 涉及到的字段是 pro表的 字段 ID 商品名称 价格 购买数量 付款 类别ID
  • 快速基于nodeJS+vue+vuex+mysql+redis建立一个后台管控系统

    structure admin structure admin是一个后台管控系统的架子 技术栈 nodeJS vue vuex mysql redis 前端使用vue的element ui的组件库 后端使用nodeJS的服务 数据库mysq
  • 求一行字符串的长度。(C语言)

    代码 include
  • hadoop集群搭建

    文章目录 一 基本配置 所有节点 一 配置静态网络 二 修改主机名和修改host文件 三 禁用SELINUX 四 关闭防火墙 并取消开机自启动 五 配置NTP时间同步 集群所有节点 六 下载一下vim编辑器 七 安装JDK1 8 八 创建h
  • 【Mysql高级】【第十五章】【锁】

    锁 1 概述 2 Mysql并发实务访问相同记录 2 1 读 读 2 2 写 写 2 3 读 写或者写 读 2 4 并发问题的解决方案 3 锁的不同角度分类 3 1 从数据操作的类型划分 读锁 写锁 0 行级别x锁 和 s锁的兼容性问题 1
  • qt connect多次

    1 坑的现象 有时项目中一个信号发出 对应连接的槽函数会执行多次 普通刷新界面都不会有问题 但是特别频繁的就会影响性能 如果是改变数据的 更有甚者会异常崩溃 2 遇坑的原因 qt中同一实例的同一信号和槽 connect多次 当信号发出时 槽
  • AD9 PCB文件黑色区域如何改变?

    PCB的大小是由KeepOut层定义的 用机械层定义有时候 黑色区域无这方面的意义 改变黑色区域大小可以用Design BoardShape RedefineBoardSharp来完成
  • 国内外常用公共NTP网络时间同步服务器地址

    目录 太长不看 NTP Pool Project NTP ORG CN NTP授时快速域名服务 HSDN Home Server Data Network 本地服务器数据网络 企业 阿里巴巴 腾讯 微软 苹果 谷歌 Facebook Clo
  • 从零开始学C++之STL(一):STL六大组件简介

    一 STL简介 一 泛型程序设计 泛型编程 generic programming 将程序写得尽可能通用 将算法从数据结构中抽象出来 成为通用的 C 的模板为泛型程序设计奠定了关键的基础 二 什么是STL 1 STL Standard Te
  • 高校圆桌派-解惑关于IT行业的3+N个问题

    高校圆桌派 话题风暴等你来 即日起参与 高校圆桌派 活动 就有机会获得CSDN高校圆桌大礼包和CSDN周边礼品免费包邮送到家 关于高校圆桌派 高校圆桌派活动是由CSDN高校俱乐部官方发起 征集同学们感兴趣的IT行业问题或大家最关心的热门话题
  • matlab中imrote,基于MATLAB的车牌识别系统的设计与研究

    基于MATLAB的车牌识别系统的设计与研究 基于MATLAB的车牌识别系统的设计与研究 摘要 汽车牌照自动识别系统是智能交通系统的重要组成部分 主要包括图像采集 图像预处理 车牌定位 字符分割 字符识别等五个核心部分 并提出了一套基于MAT
  • html左边多级菜单导航栏,精美的多级侧边栏导航菜单jQuery插件

    这是一款基于bootstrap的精美多级侧边栏导航菜单jQuery插件 该导航菜单在bootstrap样式的基础上 通过jQuery来为导航菜单绑定菜单点击事件 生成非常漂亮的多级侧边栏导航菜单 使用方法 在页面中引入bootstrap样式
  • prometheus监控k8s kube-proxy target down

    prometheus kube proxy target down 解决 修改配置 kubectl edit cm kube proxy n kube system metricsBindAddress 0 0 0 0 10249 删除 k
  • 2050年全部人口的86%集中到城市,智慧城市的五项关键技术

    本文翻译至 http readwrite jp cities 32108 人口的城市化毫不停息 人们的住所越来越多地从地方移动到城市 到2050年为止预计发达国家人口的86 发展中国家人口的64 将住在城市 数量有限的城市要负担如此多的人口
  • 查看并设置Linux的IP地址

    ip addr 查看网卡分配情况 如发现IP地址为 127 0 0 1 这里要修改ip地址 修改IP地址方法 1 进入 etc sysconfig network scripts 注 不同版本ifcfg ens33文件名可能会不一样 2 修
  • Visual C++ MFC的图形绘制——常见问题汇总

    Visual C MFC的图形绘制 常见问题汇总 目录 一 常见问题 1 菜单界面制作 2 命令响应函数 3 添加私有变量 4 消息响应函数 二 后记 三 补充代码 一 常见问题 1 菜单界面制作 题目描述 新建一个单文档类型的MFC Ap
  • 别再写满屏的 if、else 了,试试策略模式

    你还在写满屏的 if else switch 之类的判断逻辑吗 栈长在开发人员的代码中看过太多这样的低级代码了 真的太 low 极不好维护 本文栈长就教你如何用策略模式干掉 if else switch 让你的代码更优雅 什么是策略模式 比
  • 一起自律打卡社群第3期

    如果你愿意 你可以变得更好 社群大家都知道是怎么回事 建这个群组主要就是互相鼓励 一起前进 不要在生活或工作学习中处于一种颓废的状态 干啥都提不上劲 对生活也没有多大的期望 其实都是懒散惯了 导致对生活缺少一种积极的能量 从而想伪躺平当个咸
  • 电脑系统重装后触控板用不了了(消失了)

    问题 win10系统重装后发现触控板用不了 消失了 如图 正常的情况应该如图下 造成这种情况的原因 1 可能是误删触控板驱动 2 可能是重装系统的时候触控板驱动没打上 3 可能是触控板因进水 撞击损坏 4 略 可能因素太多了 这次我主讲华硕
  • express+websocket实现线上聊天

    1 webSocket简介 WebSocket是一种通信协议 可在单个TCP连接上进行全双工通信 WebSocket使得客户端和服务器之间的数据交换变得更加简单 允许服务端主动向客户端推送数据 在WebSocket API中 浏览器和服务器