【WebSocket 协议】Web 通信的下一步进化

简介: 【WebSocket 协议】Web 通信的下一步进化


WebSocket 是基于单个 TCP 的双向计算机通信协议


你可以在简单的谷歌、百度搜索中找到许多类似的定义,但是我想通过一些简单和明显的例子来说明这这些。


一、什么是 WebSocket ?


作为 HTML5 计划的一部分,开发的 WebSocket 规范引入了 WebSocket JavaScript 接口,该接口定义了一个全双工单套接字连接,通过该连接可以在客户端和服务器之间发送消息。


WebSocket 标准简化了双向 Web 通信和连接管理的大部分复杂性。


Comet Ajax 相比,WebSocket 代表了 Web 通信的下一个进化步骤。当然每种技术都有其独特的功能。


WebSocket 从 ws:// 或 wss:// 开始。它是一个有状态的协议,这意味着客户端和服务器之间的连接将保持活动状态,直到它被任何一方(客户端或服务器)终止。客户端和服务器中的任何一个关闭连接后,连接都会从两端终止。


让我们举一个客户端与服务器通信的例子,客户端是一个网络浏览器,每当我们启动客户端和服务器之间的连接时,客户端与服务器进行握手并决定创建一个新的连接和这个连接将保持活动状态,直到被其中任何一个终止。当连接建立并处于活动状态时,通信将使用相同的连接通道进行,直到终止。


以下就是 WebSocket 连接所涉及的步骤。


  1. 客户端(浏览器)向服务器发送 HTTP 请求。
  2. 通过 HTTP 协议建立连接。
  3. 如果服务器支持 WebSocket 协议,则同意升级连接。(握手)
  4. 现在握手已经完成,初始 HTTP 连接被使用相同底层 TCP/IP 协议的 WebSocket 连接替换。
  5. 此时,数据可以在 Client 和 Server 之间自由来回流动。



二、WebSocket 应用场景?

首先,在不使用 WebSocket 的情况下访问网站。 网页通常通过 HTTP 连接在 Internet 上传输。为此客户端会为您执行的每个操作向服务器发出请求。使用 HTTP 访问网站时,客户端必须先向服务器提交请求。然后服务器通过发送请求的连接来响应。换句话说,HTTP 在基本的请求和响应架构上运行,会导致大量延迟。


我举一个实在点的例子:


我们平时点外卖


0秒:食物到了吗?(客户)

0秒:正在配送。(外卖小哥)

1秒:食物到了吗?(客户)

1秒:正在配送。(外卖小哥)

2秒:食物到了吗?(客户)

2秒:正在配送。(外卖小哥)

3秒:食物到了吗?(客户)

3秒:是的,先生,这是您的外卖。(外卖小哥)


这就是我们常见的所说的 HTTP 轮询。


客户端向服务器重复请求并检查是否有任何消息要接收。


如您所见,这不是很有效。我们正在使用不必要的资源,失败的请求数量也很麻烦。


有没有办法克服这个问题?


是的,有一种轮询技术可以用来克服这个缺陷,它被称为 长轮询。即:长轮询基本上涉及向服务器发出 HTTP 请求,然后保持连接打开以允许服务器稍后响应(由服务器确定)。


长轮询版本:


0秒:食物到了吗?(客户)

3秒:是的,先生,这是您的外卖。(外卖小哥)


尽管长轮询有效,但它在 CPU、内存和带宽方面消耗的非常高(因为我们在保持连接打开时阻塞了资源)。


那么我们的救星就是:WebSocket。


WebSocket 协议的情况有所不同,可以使用动态调用方法实时调用。客户端所要做的就是通过传输 WebSocket 协议的握手来与服务器建立连接。这种握手提供了数据传输所需的所有识别信息。


客户端(Web 浏览器)初始化连接,并定期发送“心跳”以告诉服务器连接始终处于活动状态,一旦建立连接,客户端和服务器(与 http 规范相反)可以向对方发送信息(也称为服务器推送)。


这也与客户端驱动的 xmlhttprequest (ajax) 不同:客户端询问服务器它的状态是否是最新的,如果不是则更新,握手后通道保持打开状态,以实现近乎恒定的通信。


这意味着服务器可以自行传递数据,而无需客户端请求。因此,如果服务器接收到新数据,它会将其传递给客户端,而无需客户端发出特殊请求。


是不是特别好?所以应用场景也就很明显了


  • 聊天程序
  • 社交平台
  • 网络游戏

所有凡是需要客户端与服务端实时通信的场景都可以使用



三、代码中的 WebSocket

对于 WebSocket 代码的实现,我们只需要 (编程语言或者框架名 + WebSocket) 关键词搜索引擎检索一下 就可以实现


以下为不完整统计!仅供参考~


WebSocket 目前支持以下浏览器:

  • Internet Explorer:版本 10 或更高版本
  • Firefox:版本 6 或更高版本
  • Chrome:版本 14 或更高版本
  • Opera:版本 12.10 或更高版本
  • Safari:版本 6 或更高版本

在服务器端,WebSocket 可以与以下编程语言和框架一起使用:

  • Node.js

Socket.IO

WebSocket-Node

ws

  • Java

Jetty

  • Python

pyWebSocket

Tornado

  • C++

Libwebsockets



四、一个完美的案例:在线聊天程序


服务端: node.js

前端: html+css+javascript



实现服务器


让我们开始写服务器代码

首先,创建一个名为chat的文件夹。进入此文件夹并通过在终端中输入 npm init

初始化项目,或者 yarn init 。 现在我们已经初始化了我们的应用程序。


我们需要准备两个包


npm install ws serve-handler

这里的 ws 它是 Node.js 的纯 WebSocket 实现。


根目录的 package.json 中记得加入 "type": "module"


41.png

chat/index.js

import {createServer} from 'http';
import staticHandler from 'serve-handler';
import ws, {WebSocketServer} from 'ws';
// 创建服务
const server = createServer((req, res) => {
    return staticHandler(req, res, {public: 'public'})
});
// 创建一个WebSocket服务器
const wss = new WebSocketServer({server})
// 当有新的连接时
wss.on('connection', (client) => {
    // 客户端连接
    console.log('Client connected !')
    client.on('message', (msg) => {
        // 客户端发送消息
        console.log(`Message:${msg}`);
        broadcast(msg)
    })
})
// 发送消息
function broadcast(msg) {
    for (const client of wss.clients) {
        if (client.readyState === ws.OPEN) {
            client.send(msg)
        }
    }
}
server.listen(process.argv[2] || 8080, () => {
    console.log(`server listening...`);
})


实现客户端

接下来,是时候实现我们的聊天应用程序的客户端了。本质上是一个带有一些基本 JavaScript 代码的最小 HTML 页面。



chat/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">
        <link rel="stylesheet" href="style.css">
        <title>聊天室</title>
    </head>
    <body>
        <div class="container">
            <p class="msg">消息:</p>
            <div id="messages" class="messages"></div>
            <form id="msgForm" class="msgForm">
                <input type="text" placeholder="Send message" class="input" id="inputBox"/>
                <input type="submit" class="btn" value="发送">
            </form>
        </div>
        <script type="text/javascript">
            // 初始化
            const ws = new WebSocket(`ws://localhost:8000`);
            ws.binaryType = "blob";
            // 连接成功
            ws.addEventListener("open", event => {
                console.log("Websocket 连接打开");
            });
            // 关闭连接
            ws.addEventListener("close", event => {
                console.log("Websocket 连接关闭");
            });
            // 消息事件
            ws.onmessage = function (message) {
                const msgDiv = document.createElement('div');
                msgDiv.classList.add('msgCtn');
                // 获取消息
                if (message.data instanceof Blob) {
                    reader = new FileReader();
                    // 接收到消息时触发
                    reader.onload = () => {
                        msgDiv.innerHTML = reader.result;
                        document.getElementById('messages').appendChild(msgDiv);
                    };
                    // 读取消息
                    reader.readAsText(message.data);
                } else {
                    // 显示消息
                    console.log("Result2: " + message.data);
                    msgDiv.innerHTML = message.data;
                    document.getElementById('messages').appendChild(msgDiv);
                }
            }
            // 发送消息
            const form = document.getElementById('msgForm');
            form.addEventListener('submit', (event) => {
                event.preventDefault();
                const message = document.getElementById('inputBox').value;
                // 发送
                ws.send(message);
                document.getElementById('inputBox').value = ''
            })
        </script>
    </body>
</html>

chat/style.css

接下来我们让页面变的好看一点

html {
    font-size: 62%;
}
body {
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center;
}
.container {
    margin-top: 5rem;
    display: flex;
    flex-direction: column;
    width: 30%;
    height: 70vh;
}
.msg {
    color: blueviolet;
    font-size: 2rem;
}
.msgCtn {
    margin: 1rem 0;
    color: white;
    padding: 1rem 1rem;
    background-color: blueviolet;
    border-radius: 6px;
    font-size: 2rem
}
.msgForm {
    display: flex;
    flex-direction: row;
}
.input {
    height: 100%;
    flex: 4;
    margin-right: 2rem;
    border: none;
    border-radius: .5rem;
    padding: 2px 1rem;
    font-size: 1.5rem;
    background-color: aliceblue;
}
.input:focus {
    background-color: white;
}
.btn {
    height: 5rem;
    flex: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: .5rem;
    background-color: blueviolet;
    color: whitesmoke;
    border: none;
    font-size: 1.6rem;
}


最终效果

让我们运行


node index.js 8000

然后运行 index.html 这个就不多描述了


打开两个窗口,效果如下:


image.png



目录
相关文章
|
2月前
|
前端开发 JavaScript 网络协议
深入理解Python Web开发中的前后端分离与WebSocket实时通信技术
【7月更文挑战第18天】前后端分离采用Flask/Django框架,前端JavaScript框架如Vue.js与后端通过AJAX/Fetch通信。WebSocket提供实时双向通信,Python可借助websockets库或Flask-SocketIO实现。最佳实践包括定义清晰的接口规范,确保安全性(HTTPS,认证授权),优化性能,和健壮的错误处理。结合两者,打造高效实时应用。
69 1
|
8天前
|
移动开发 JSON Java
Jmeter实现WebSocket协议的接口测试方法
WebSocket协议是HTML5的一种新协议,实现了浏览器与服务器之间的全双工通信。通过简单的握手动作,双方可直接传输数据。其优势包括极小的头部开销和服务器推送功能。使用JMeter进行WebSocket接口和性能测试时,需安装特定插件并配置相关参数,如服务器地址、端口号等,还可通过CSV文件实现参数化,以满足不同测试需求。
53 7
Jmeter实现WebSocket协议的接口测试方法
|
19天前
|
机器学习/深度学习 自然语言处理 网络协议
为什么ChatGPT采用SSE协议而不是WebSocket?
在探讨大型语言模型ChatGPT的技术实现时,一个引人注目的细节是其选择使用SSE(Server-Sent Events)协议而非WebSocket来实现数据的实时推送。这一选择背后,蕴含着对技术特性、应用场景及资源效率的深思熟虑。本文将深入探讨ChatGPT为何偏爱SSE,以及这一决策背后的技术逻辑。
38 2
|
1月前
|
网络协议
Web基础与HTTP协议
【8月更文挑战第10天】
35 2
|
1月前
|
前端开发 网络协议 物联网
Django Web:搭建Websocket服务器(入门篇)
Django Web:搭建Websocket服务器(入门篇)
36 1
|
20天前
|
数据处理 开发者 监控
揭秘实时Web应用开发:WebSocket与Akka Streams如何让Play Framework如虎添翼?
【8月更文挑战第31天】实时Web应用需求日益增长,覆盖了从即时通讯到在线游戏等多个领域。Play Framework结合WebSocket与Akka Streams,简化了高效实时应用的开发。WebSocket提供全双工通信,使服务器能主动向客户端推送消息;Akka Streams支持声明式数据流处理,有效避免系统因数据处理不及时而崩溃。本文通过示例代码展示了如何利用这些技术构建实时股票报价系统,展现了其在实时数据处理方面的强大能力。掌握这一技术组合,将大幅提升你在实时Web应用开发中的效率与稳定性。
22 0
|
1月前
|
网络协议
Web中的HTTP协议
Web中的HTTP协议
|
1月前
|
开发框架 .NET API
.Net Core Console 项目如何使用 HttpClient 与 Web 服务通信
.Net Core Console 项目如何使用 HttpClient 与 Web 服务通信
|
2月前
|
前端开发 JavaScript API
探索Python Django中的WebSocket集成:为前后端分离应用添加实时通信功能
【7月更文挑战第17天】现代Web开发趋势中,前后端分离配合WebSocket满足实时通信需求。Django Channels扩展了Django,支持WebSocket连接和异步功能。通过安装Channels、配置设置、定义路由和消费者,能在Django中实现WebSocket交互。前端使用WebSocket API连接后端,实现双向数据流,如在线聊天功能。集成Channels提升Web应用的实时性和用户体验,适应实时交互场景的需求。**
114 6
|
2月前
|
JavaScript 前端开发 网络协议
从理论到实践:全面剖析Python Web应用中的WebSocket实时通信机制
【7月更文挑战第17天】WebSocket在实时Web应用中扮演重要角色,提供全双工通信,减少延迟。本文详述了Python中使用`websockets`库创建服务器的步骤,展示了一个简单的echo服务器示例,监听8765端口,接收并回显客户端消息。客户端通过JavaScript与服务器交互,实现双向通信。了解WebSocket的握手、传输和关闭阶段,有助于开发者有效利用WebSocket提升应用性能。随着实时需求增长,掌握WebSocket技术至关重要。
209 6