Websocket的基本使用-聊天室案例

news2024/11/17 7:45:53

1. 什么是websocket

WebSocket 是一种网络通信协议

2. 为什么需要websocket

Websocket 协议,是为了弥补HTTP协议【单向通信】的缺点。

详细来讲,HTTP只支持由客户端发起通信,一旦服务端的数据发生变化,是不可能主动向客户端推送消息的。

一般而言,此时都会使用【轮询 + HTTP】的解决方案,即每隔一段时间就建立一次HTTP连接,来帮助客户端追加更新。但效率非常低,非常浪费资源。

websocket 则支持服务器推送技术。

即,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,实现真正的双向平等对话。

客户端和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

3. websocket简介

websocket 特点

(1)实时通信:全双工协议,延迟更少,效率更高。

(2)与HTTP协议有良好的兼容性:默认端口也是80 和 443,并且握手阶段采用HTTP协议,可以通过各种HTTP代理服务器,不容易被屏蔽。

(3)控制开销:用于协议控制的数据包头部相对较小,数据格式比较简洁,性能开销比较小,通信高效。

(4)二进制传输:可以发送文本,也可以发送二进制数据。

(5)没有同源限制:可以实现客户端和服务器的任意通信。

(6)实现简单:建立在TCP协议之上,服务器端的实现比较简单。

webSocket 与 HTTP 的异同

相同点:

(1)都是基于TCP的应用层协议。

(2)都使用Request/Response模型进行连接的建立。

(3)在连接的建立过程中对错误的处理方式相同,在这个阶段WebSocket可能返回和HTTP相同的返回码。

不同点:

(1)HTTP协议基于Request/Response,只能做单向传输,是半双工通信,而WebSocket是全双工通信

 - 半双工通信:单向流动, 服务器不主动推送数据给客户端

 - 全双工通信:服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。

(2)http是无状态的,所以请求得到响应以后就关闭了,无状态的好处是服务器不需要存储相关会话信息。缺点是每次http请求和响应都会发送关于请求的冗余信息;而WebSocket 只需要建立一次Request/Response消息对,之后都是TCP连接,避免了需要多次建立Request/Response消息对而产生的冗余头部信息。节省了大量流量和服务器资源。

(3)WebSocket在建立握手连接时,数据是通过HTTP协议传输的,但在建立连接之后,真正的数据传输阶段是不需要HTTP协议参与的。而http需要需要三次握手。

(4)WebSocket传输的数据是二进制流,是以帧为单位的,HTTP传输的是明文传输,是字符串传输。

4. 客户端的简单应用

事件:onopen、onmessages、onclose、onerror

const ws = new Websocket("wss://echo.websocket.org");

// onopen:用于执行连接成功后的回调

ws.onopen = function(evt){

    consoel.log("===========连接开始==========");

    ws.send("Hello WebSocket!");

}

// onmessage:用于指定收到服务器数据后的回调

ws.onmessage = function(evt){

    console.log("收到数据:" + evt.data);

    ws.close();

}

// onopen:用于执行连接断开后的回调

ws.onclose = function(evt){

    consoloe.log("==========连接关闭==========");

}

ws.onerror = function(event) {

  consoloe.error("==========连接有误==========");

};

以上 `onopen、onmessage、onclose`如果需要指定多个回调,就可以使用监听形式。

// 以onopen为例

ws.addEventListener("open",(event)=>{
    const code = event.code;
    const reason = event.reason;
    const wasClean = event.wasClean;

})

方法:send() | close()

send() : 在连接成功后关闭前,发送消息(onopen后和onclose前才可发送消息)。

close() : 关闭连接

`webSocket` 实例对象的`send()`,用于向服务器发送数据。代码为:ws.send("")

webSocket.readyState

Websocket.CONNECTING: 值为0,表示正在连接

Websocket.OPEN:值为1,表示连接成功

Websocket.CLOSING:值为2,表示连接关闭

Websocket.CLOSED:值为3,表示连接已经关闭,或者打开连接失败

switch (ws.readyState) {

  case WebSocket.CONNECTING:

    // do something

    break;

  case WebSocket.OPEN:

    // do something

    break;

  case WebSocket.CLOSING:

    // do something

    break;

  case WebSocket.CLOSED:

    // do something

    break;

  default:

    // this never happens

    break;

}

webSocket.bufferedAmount

bufferedAmount 是一个数值,表示还有多少字节的二进制数据没有发送,常用于判断发送数据是否结束

var data = new ArrayBuffer(10000000);

socket.send(data);

if (socket.bufferedAmount === 0) {
  // 发送完毕
} else {
  // 发送还没结束
}

// 限制客户端向服务器发送数据的频率
const ws = new WebSocket("ws://echo.websocket.org/updates");

ws.onopen = function(){
    setInterval(()=>{
        if(ws.bufferedAmount < 10240){
            ws.send(getApplicationState());
        }
    },1000);
}

5. 服务端的应用

常用的 Node 实现有以下三种。

 - WebSockets

 - Socket.IO

 - WebSocket-Node
 

6. 简单聊天室的实现——node

6.1 服务端

1. 创建一个空文件夹, `npm init -y` 初始化

2. `npm install websocket`

3. 创建`server.js`

// 因为websocket 是基于 http 协议的,因此 http 和 websocket 模块都需要被引入
const http = require("http");
const websocket = require("websocket").server;

const httpServer = http.createServer().listen(8080,()=>{
    console.log("Hello localhost:8080!");
})

// websocket 是基于 http 协议的,这两个参数必填
const websocketServer = new websocket({
    httpServer: httpServer,
    autoAcceptConnections:false
})

// 创建通信线池:不用数据库的话,一般用数组来模拟一个虚拟线池。
const connecttionArr = [];

// 用npm包中的API:on()监听事件
websocketServer.on('request', function(request) {
    // 这是一次客户端发送的消息,只要连接没断开,这个连接就需要被存储起来
    const connection = request.accept()

	// 每次接收一个链接,将它存放在数组里面
	connecttionArr.push(connection)

    // 监听客户端发送的消息
    connection.on('message', function(message) {
        console.log(message);
        // 消息转换编码
        // 发送消息给客户端(取出所有的链接,即可广播到各个客户端)
        for(let i =0; i<connecttionArr.length ;i++){
            connecttionArr[i].send(message.utf8Data);
        }
    })
})

配置好`server.js`后,`node server.js`启动服务器即可

6.2 客户端

客户端的websocket服务就是浏览器的API调用

<!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" id="uName">
    <br>
    输入消息:<input type="text" id="context">

    <button id="btn"> 点击发送消息 </button>

    <div id="charRoom"></div>

</body>
<script>
    // 用户名
    const uName = document.getElementById('uName')
    // 文本框内容
    const context = document.getElementById('context')
    // 点击按钮
    const btn = document.getElementById('btn')
    // 要显示聊天室的区域
    const charRoom = document.getElementById('charRoom')

    // 实例化 websocket
    const websocket = new WebSocket('ws://localhost:8080')

    // 建立链接
    websocket.onopen = function() {
        console.log(websocket.readyState);
    }

    btn.onclick = ()=>{
        // 将用户名和要发送的内容放在一个对象中,一起传送给后端
        const info = {
            uName : uName.value,
            context: context.value
        }
        // 清空文本框的内容
        uName.value = "";
        context.value = "";
        // 通过 websockte 发送消息
        websocket.send(JSON.stringify(info));
    }

    // 监听服务器传送来的消息
    websocket.onmessage = function(event){
        const chatInfo = JSON.parse(event.data);

        charRoom.innerHTML += `
            <strong>${chatInfo.uName}:</strong>
            <span>${chatInfo.context}</span>
            <br />
        `
    }

</script>
</html>

6.3 效果

 7. 简单聊天室的实现——socket.io

7.1 服务端

1. 创建一个空文件夹, `npm init -y` 初始化

2. `npm install socket.io`

3. 创建`server.js`

// socket.io 框架
// 引入 http 模块的 createServer 方法
const { createServer } = require('http')

// 引入 socket.io 的 Server 模块
const { Server } = require('socket.io')

// 实例化 httpServer
const httpServer = createServer();

// 初始化 socket.io
const io = new Server(httpServer, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST']
  }
})

// 使用 socket.io 来建立连接
io.on('connection', socket => {
  socket.on('sendMsg', data => {
    io.emit('pushMsg', data)
    console.log(data);
  })
})

// 创建服务器,进行监听
httpServer.listen(8080, function() {
  console.log('http://localhost:8080');
})

7.2 客户端

客户端需要引入`socket.io`框架

<!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>
    <script src="https://cdn.socket.io/4.4.0/socket.io.min.js"
    integrity="sha384-1fOn6VtTq3PWwfsOrk45LnYcGosJwzMHv+Xh/Jx5303FVOXzEnw0EpLv30mtjmlj" crossorigin="anonymous">
    </script>
</head>
<body>
    输入姓名:<input type="text" id="uName">
    <br>
    输入消息:<input type="text" id="context">

    <button id="btn"> 点击发送消息 </button>

    <div id="charRoom"></div>
</body>
<script>
    // 用户名
    const uName = document.getElementById('uName')
    // 文本框内容
    const context = document.getElementById('context')
    // 点击按钮
    const btn = document.getElementById('btn')
    // 要显示聊天室的区域
    const charRoom = document.getElementById('charRoom')

    // 使用 socket.io 框架与服务器相连接
    const socket = io.connect('http://localhost:8080')

    // 点击发送消息的事件
    btn.onclick = function() {
        // 将用户名和要发送的内容放在一个对象中,一起传送给后端
        const values = {
            uName: uName.value,
            context: context.value
        }

        // 清空文本框的内容
        uName.value = ''
        context.value = ''

        // 通过 socket.io 框架向服务器发送数据
        socket.emit('sendMsg', values)
    }

    // 使用 socket.on 方法监听服务端发送过来的数据
    socket.on('pushMsg', data => {
        // 添加到页面上
        charRoom.innerHTML += `
            <strong>${data.uName}:</strong>
            <span>${data.context}</span>
            <br />
        `
    })
</script>
</html>

7.3 效果

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1550591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构——二叉搜索树详解

一、二叉搜索树定义 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 1.非空左子树上所有节点的值都小于根节点的值。 2.非空右子树上所有节点的值都大于根节点的值。 3.左右子树也都为二叉搜索树。 如下图所示&#xff1a…

SinoDB备份恢复工具之ontape

ontape是SinoDB数据库的备份恢复工具之一&#xff0c;可以记录、备份与恢复数据。因为不涉及到存储管理器&#xff0c;所以可以轻松实现其他备份方法&#xff0c;比如备份到 STDIO&#xff08;标准输出&#xff09;或备份到云。 1. ontape功能特性 备份数据库服务器实例支持增…

【蓝桥杯省赛真题34】python积木搭建 中小学青少年组蓝桥杯比赛 算法思维python编程省赛真题解析

python积木搭建 第十三届蓝桥杯青少年组python比赛省赛真题 一、题目要求 &#xff08;注&#xff1a;input&#xff08;&#xff09;输入函数的括号中不允许添加任何信息&#xff09; 1、编程实现 小蓝和小青在玩积木搭建游戏&#xff0c;具体玩法如下: 小蓝报一个数字N&…

展示大屏-24小时天气预报

一、项目说明 展示大屏显示未来一周天气和24小时天气详情。 二、技术工具 1.语言&框架&#xff1a;java、springboot 2.UI界面&#xff1a;jQuery、HTML、CSS、 VUE 3.开发工具&#xff1a;IntelliJ IDEA、Eclipse 三、实现步骤 后端步骤 1.调取免费或收费的API接口。 …

【一】TensorFlow神经网络模型构建之神经元函数及优化方法

TensorFlow神经网络模型构建主要涉及如下几块&#xff1a;神经元函数、卷积函数、池化函数、分类函数、优化方法。下面分别对这几块进行展开说明&#xff1a; 神经元函数及优化方法 神经网络之所以能解决非线性问题&#xff08;如语音、图像识别等&#xff09;&#xff0c;本…

共建数治政务,共赢数智未来——锐捷网络召开2024政府行业全国核心合作伙伴大会

在我国不断推进现代化产业体系建设,新质生产力正进入跃迁式发展的今天,加速政府的数字化转型,促进数字技术与政府应用深度融合,也正成为越来越多地方政府的共识。为了更好地携手合作伙伴共同把握数智政务建设新契机、聚力提升数智政务建设新能力,3月22日,以“共建数治政务,共赢…

C++第十三弹---内存管理(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、operator new与operator delete函数 1.1、operator new与operator delete函数 2、new和delete的实现原理 2.1、内置类型 2.2、自定义类型 …

星光/宝骏/缤果/长安 车机CarPlay手机操作破解教程V2.0版本(无需笔记本、无需笔记本、无需笔记本)

之前写了个1.0版本&#xff0c;由于太局限&#xff0c;需要用到笔记本才能操作&#xff0c;很多车友反馈不方便。特此出个手机版教程&#xff0c;简单easy&#xff0c;妈妈再也不用担心我搞不定啦 一、准备工作 先卸载车机上的autokit 或者 智能互联 app&#xff0c;这步很关…

使用Qt生成图片

Qt之生成png/jpg/bmp格式图片_qt生成图片-CSDN博客 (1)使用QPainter 示例关键代码&#xff1a; QImage image(QSize(this->width(),this->height()),QImage::Format_ARGB32);image.fill("white");QPainter *painter new QPainter(&image);painter->…

详解 WebWorker 的概念、使用场景、示例

前言 提到 WebWorker&#xff0c;可能有些小伙伴比较陌生&#xff0c;不知道是做什么的&#xff0c;甚至不知道使用场景&#xff0c;今天这篇文章就带大家一起简单了解一下什么是 webworker&#xff01; 概念 WebWorker 实际上是运行在浏览器后台的一个单独的线程&#xff0…

[PCL] PCLVisualizer可视化的应用

[PCL] PCLVisualizer可视化的应用 通常情况下 PCL的可视化 是非常方便. 但是 #include<pcl/io/io.h> #include<pcl/io/pcd_io.h> #include<pcl/io/ply_io.h> #include<pcl/visualization/cloud_viewer.h>#include<iostream> #include<threa…

【函数修改的重要问题】想要增加C++函数返回值,选择结构体?OR 额外参数?

作为一个程序员&#xff0c;我们经常会遇到这样的情况&#xff1a; 别人写的C项目&#xff0c;需要我们来进行 ”修改&#xff0c;或者增加功能“。 举个例子 我们需要对于一个已有的C函数&#xff0c;增加它的返回值信息&#xff0c;通常有两条路可走&#xff1a; 用结构体…

只用一部手机,为你的吉利车机安装第三方软件(支持大部分车型)

&#x1f4a1; 文中使用的方法为DNS重定向&#xff0c;需要你具备一定的动手能力&#xff0c;否则将无法达到最终目的。 &#x1f4a1; 阅读本文&#xff0c;视为你有一定电脑基础&#xff0c;难以理解时&#xff0c;请寻求百度帮助&#xff0c;百度就是最好的老师&#xff01;…

“大模型+机器人”的现状和未来,重磅综述报告来了!

基础模型(Foundation Models)是近年来人工智能领域的重要突破&#xff0c;在自然语言处理和计算机视觉等领域取得了显著成果。将基础模型引入机器人学&#xff0c;有望从感知、决策和控制等方面提升机器人系统的性能&#xff0c;推动机器人学的发展。由斯坦福大学、普林斯顿大学…

红队笔记8-CTF5打靶流程-CMS漏洞-多用户信息泄露(vulnhub)

目录 开头: 1.主机发现和端口扫描&#xff1a; 2.80端口-NanoCMS哈希密码信息泄露-后台getshell 3.提权-用户过多信息泄露 4.总结&#xff1a; 开头: 学习的视频是哔哩哔哩红队笔记&#xff1a; 「红队笔记」靶机精讲&#xff1a;LAMPSecurityCTF5 - 标准攻击链&#xff…

【Java程序设计】【C00392】基于(JavaWeb)Springboot的校园生活服务平台(有论文)

基于&#xff08;JavaWeb&#xff09;Springboot的校园生活服务平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过…

有趣的css - 多弧形加载动画

大家好&#xff0c;我是 Just&#xff0c;这里是「设计师工作日常」&#xff0c;今天分享的是用纯css实现多双弧线加载动画。 《有趣的css》系列最新实例通过公众号「设计师工作日常」发布。 目录 整体效果核心代码html 代码css 部分代码 完整代码如下html 页面css 样式页面渲…

MySQL数据库基础--约束

约束 约束是作用于表中字段上的规则&#xff0c;用于限制在表中的数据 目的&#xff1a;保证数据库中数据的正确&#xff0c;有效性和完成性。 分类&#xff1a; 注意&#xff1a;约束是作用于表中字段上的&#xff0c;可以在创建表/修改表的时候哦添加约束 外键约束 外键用…

心理治疗聊天机器人的调查

摘要 这项调查旨在调查、分析和比较现有聊天机器人在心理治疗中的可行性和缺陷。调查指出了未来心理治疗聊天机器人所需的一系列任务。我们在公共数据库中检索了约1200篇相关文献&#xff0c;并选择了五种典型的和最先进的心理治疗聊天机器人。大多数最先进的心理治疗聊天机器人…