当前位置: 首页 > news >正文

websoket是干么的如何基于websoket实现一个简单的消息通信。

websoket是干么的

  1. websoket简单来说就是允许服务端主动向客户端推送数据的一种技术。他可以使客户端和服务端之间交换数据变得简单,浏览器和服务器只需要完成一次握手(握手指的是:创建websoket需要向浏览器发送请求,之后服务器进行回应,这个过程称为握手),两者之间就可以创建持久的连接,进行双向数据传输。

  1. websoket是一种在单个TCP连接上进行的全双工通信的协议。由于协议是全双工的,所以服务器可以随时主动给客户端下发数据相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少;

  1. 保持连接状态。与HTTP不同的是,Websocket需要先创建连接,这就使得其成为一种有状态的协议,之后通信时可以省略部分状态信息。而HTTP请求可能需要在每个请求都携带状态信息(如身份认证等

很多网站为了实现推送技术,一般用的技术都是轮询(轮询简单来说:使用定时器每隔一段时间向后端发送一次请求俗称:程控输出入)由浏览器对服务器发出 HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的 头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

基于websoket实现一个简单的消息通信

使用到的技术有vite node ws

先初始化两个项目一个web端的,一个服务端

npm init -y

npm i vite -D

更改启动命令

{
  "name": "web",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "vite"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "vite": "^4.0.4"
  }
}

创建 index.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>
    <h1>欢迎来到聊天室</h1>
    <ul id="ul">
    </ul>
    <input id="input" type="text">
    <button id="btn">点击发送</button>
</body>
<script>
    // 1 安装vite npm i vite -D
    /** 前端
     * open 建立连接
     * close 关闭连接
     * error 错误信息
     * message 接受后端返回的信息
     * */

    ; ((Window, WebSocket, Storage) => {
        console.log(localStorage.getItem('name'))
        let ws = new WebSocket('ws:localhost:8000')

        function bindTab() {
            btn.addEventListener('click', btnHandle)
            ws.addEventListener('message', messageHandle)
            ws.addEventListener('close', closeHandle)
            ws.addEventListener('error', errorHandle)
            ws.addEventListener('open', openHandle)
        }
        const closeHandle = () => {
            console.log('close');
        }
        const errorHandle = () => {
            console.log('error');
        }
        const openHandle = () => {
            console.log('open');
        }
        const messageHandle = (res) => {
            ul.appendChild(render(res.data))
        }
        const btnHandle = () => {
            console.log(input.value)
            if (!Storage.getItem('name')) {
                console.log(Storage.getItem('name'))
                window.location.href = 'http://127.0.0.1:5173/login.html'
            }
            let obj = JSON.stringify({
                text: input.value,
                time: new Date().toLocaleString(),
                name: localStorage.getItem('name')
            })
            console.log(2, ws)
            // 向后端发送数据将参数转换为字符串传入。
            ws.send(obj)
        }
        const render = (value) =>  {
            let msg = JSON.parse(value)
            let li = document.createElement('li')
            li.innerHTML = `
                   <li>内容:${msg.text}--姓名:${msg.name}--时间:${msg.time}</li>
               `
            return li
        }


        bindTab()

    })(Window, WebSocket, localStorage)

</script>

</html>

创建login.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>
    <h1>欢迎来到聊天室</h1>
    <p>请输入你的名字:<input id="input" type="text"> <button id="btn">注册</button></p>

</body>
<script>
    btn.addEventListener('click', function () {
        localStorage.setItem('name', JSON.stringify(input.value))
        window.location.href = 'http://127.0.0.1:5173/'
    })

</script>

</html>

node服务端

npm init -y

npm i ws -D

没有nodemon 安装 npm i nodemon

{
  "name": "node",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "nodemon": "^2.0.20",
    "ws": "^8.12.0"
  }
}

创建index.js

const Ws = require('ws')
// 监听在8000端口
const wss = new Ws.Server({
    port: 8000,
})

/** 后端
   * open 建立连接
   * close 关闭连接
   * error 错误信息
   * message 接受后端返回的信息
   * connection 后端表示已经连接上了
   * */

//   ws 插件   nodejs-websocket 插件
wss.on('open', () => {
    console.log('open')
})
wss.on('connection', function (ws) {
    console.log('连接成功', ws)
    ws.on('message', getMessage)
})

wss.on('message', (res) => {
    console.log('message', res);
})
wss.on('error', () => {
    console.log('error' );

})
wss.on('close', () => {
    console.log('close' );
})


function getMessage(msg) {
    //<Buffer 7b 22 69 64 22 3a 31 2c 22 6e 61 6d 65 22 3a 22 e5 bc a0 e4 b8 89 22
    // 必须将msg进行toString 否则会形成Buffer
    console.log('ws', msg.toString())
    // toJSON不是转成原数据json,而是把json buffer数据转化成json格式。
    console.log(msg.toJSON());
    // clients 向客户端推送数据
    wss.clients.forEach(c => {
        c.send(msg.toString())
    })
}

启动命令都是 npm run dev

相关文章:

  • nacos 服务发现获取列表源码分析
  • 【MySQL】过年没有回老家,在出租屋里整理了一些思维导图
  • 《流浪地球 2》 Deepfake 小试牛刀,45+ 吴京「被」年轻,变身 21 岁小鲜肉
  • C++工程实践必备技能
  • GitHub访问问题与FastGithub下载及使用(详细篇)
  • <使用Python自定义生成简易二维码>——《Python项目实战》
  • Spring Boot 热部署(热加载)
  • 又一个开源工具搞完了,工作效率直接翻倍
  • 入职-环境安装篇
  • 自动驾驶感知——毫米波雷达
  • MySQL运维(二)MySQL分库分表概念及实战、读取分离详解
  • K8s简介之什么是K8s
  • webgl绘制图形API——drawArrays、drawElements
  • 不平衡数据集的建模的技巧和策略
  • 每天一道大厂SQL题【Day01】
  • [分享]iOS开发-关于在xcode中引用文件夹右边出现问号的解决办法
  • 【MySQL经典案例分析】 Waiting for table metadata lock
  • co.js - 让异步代码同步化
  • Hexo+码云+git快速搭建免费的静态Blog
  • Java知识点总结(JavaIO-打印流)
  • k个最大的数及变种小结
  • opencv python Meanshift 和 Camshift
  • web标准化(下)
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 聊聊springcloud的EurekaClientAutoConfiguration
  • 使用SAX解析XML
  • - 转 Ext2.0 form使用实例
  • 大数据全解:定义、价值及挑战
  • 交换综合实验一
  • #162 (Div. 2)
  • #pragma multi_compile #pragma shader_feature
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • $forceUpdate()函数
  • (1)(1.13) SiK无线电高级配置(六)
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (南京观海微电子)——COF介绍
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (一)【Jmeter】JDK及Jmeter的安装部署及简单配置
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • .net 4.0 A potentially dangerous Request.Form value was detected from the client 的解决方案
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .NET DataGridView数据绑定说明
  • .NET 反射的使用
  • .net/c# memcached 获取所有缓存键(keys)
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .NET企业级应用架构设计系列之技术选型
  • ::什么意思
  • ?
  • @RequestParam,@RequestBody和@PathVariable 区别
  • [1] 平面(Plane)图形的生成算法
  • [AIGC] 开源流程引擎哪个好,如何选型?
  • [Android Pro] android 混淆文件project.properties和proguard-project.txt
  • [Angular] 笔记 20:NgContent
  • [AutoSar]BSW_Com02 PDU详解
  • [AutoSar]BSW_Memory_Stack_004 创建一个简单NV block并调试