资讯专栏INFORMATION COLUMN

你不知道WebSocket吗?

techstay / 2947人阅读

摘要:什么是是一种在单个连接上进行全双工通信的协议。短轮询配段代码,静态服务中间件用来返回静态文件当前价格是元获取最新价格接口客户端不停的发送请求,去服务端获取最新价格。它通过连接到一个服务器,以格式接收事件不关闭连接。

什么是WebSocket?

WebSocket是一种在单个TCP连接上进行全双工通信的协议。这里我们发现了一个有趣的词:”全双工”,那我们就来简单了解下通信方式有哪些!

单工

通信双方中,一方固定为发送端,一方则固定为接收端。信息只能沿一个方向传输。
例如计算机与打印机之间的通信是单工模式

说的简单些就是:我打你你只能忍着!

半双工

允许数据在两个方向上传输,但是同一时间数据只能在一个方向上传输,其实际上是切换的单工。
例如HTTP协议:客户端向服务器发送请求(单向的),然后服务器响应请求(单向的)

说的简单些就是:我打你,你忍完后可以打我,我忍着…

全双工

允许数据在两个方向上同时传输。
例如手机通话,WebSocket就是这个样子!

说的简单些就是:两个人同时可以互相打对方

说了这么多其实目的就是让大家知道,WebSocket是支持双向通信的!
双向通信的优点

为什么要支持双向通信?单向通信有什么问题?还是从HTTP说起,我们知道HTTP协议是半双工的,而且服务器不能主动推送消息给浏览器!这个就是他的缺陷。假若我希望实现一个股票交易系统,可能股价每秒钟都有变化,但是价格变化了如何通知我们的客户端?

咱们来看看以前是怎么实现的!

轮询

什么叫轮询?就是不停的轮番询问!说的直白些就是客户端定期发送请求给服务端。

短轮询

配段代码,Talk is cheap,show me your code.

const express = require("express");
const app = express();
// express 静态服务中间件用来返回静态文件
app.use(express.static(__dirname));
// 当前价格是100元
let currentPrice = 100;
// 获取最新价格接口
app.get("/getPrice", (req, res, next) => {
    res.send("¥"+currentPrice * Math.random());
});
app.listen(3000);

客户端不停的发送请求,去服务端获取最新价格。

当前交易价格:
很快我们就看出了这样编写代码的缺陷!如果数据变化的不快呢,那就会发送很多无意义的请求。每次发送请求都会有HTTP的Header会消耗大量流量,同时也会消耗CPU的利用率!
长轮询

长轮询是对短轮询的改进版,就是当第一个请求回来时再发送下一个请求!

(function poll(){
    fetch("/getPrice").
    then(res=>res.text()).
    then(data=>{price.innerHTML = data;poll()})
})()
问题依旧是显而易见的!如果服务端数据变化很快,那么请求数目会更多;如果变化很慢,可能ajax会出现超时的问题。
Iframe方式

我们并不希望每次都创建一个新的请求,此时就可以使用Iframe来实现长连接

app.get("/getPrice", (req, res, next) => {
    setInterval(()=>{
        // 不能使用end 否则会中断请求,我们要实现的是长连接
        res.write(`
            
        `);
    },1000);
});

    
当前交易价格:
现在确实可以利用Iframe实现了长连接通信,但是页面的状态一直是加载态!
EventSource流

EventSource 接口用于接收服务器发送的事件。它通过HTTP连接到一个服务器,以text/event-stream 格式接收事件, 不关闭连接。

当前交易价格:
app.get("/getPrice", (req, res, next) => {
    res.header("Content-Type","text/event-stream",);
    timer = setInterval(()=>{
        res.write( // 发送message事件 

表示当前的event-stream通信结束
            `event:message
id:${id++}
data:${currentPrice*Math.random()}

`
        );
    },1000);
    res.on("close",()=>{
        clearInterval(timer);
    });
});
当然这种方式依旧是单向的,主要是服务端向客户端推送数据。并且兼容性也不是很美丽~
WebSocket

终于等到你! 双向通信的WebSocket让你欲罢不能!

WebSocket让客户端和服务器保有一个持久的连接,两边可以在任意时间开始发送数据!它是基于TCP协议的:

先来聊聊WebSocket的优势!

http协议不支持双向通信 -> 我支持双向通信

http协议数据包头部较大 -> 我的header很小!我最少只需两个字节

http不支持跨域 -> 我支持跨域,哈哈!

ws模块

ws: a Node.js WebSocket library,ok就是在node中可以使用的WebSocket库!

安装ws模块

yarn add ws

服务端开启WebSocket服务

const WebSocketServer = require("ws").Server;
const ws = new WebSocketServer({port:8888});
ws.on("connection",(socket)=>{ // socket链接我的那个人
    console.log("服务端:有人链接我!");
    socket.on("message",(data)=>{
        console.log(data); // 收到客户端发来的消息
        socket.send("我是服务端"); // 给客户端发消息
    });
});

客户端链接8888端口的ws服务!

const socket = new WebSocket("ws://localhost:8888");
socket.onopen = function(){ // 链接成功后,发送消息
    console.log("客户端:链接成功");
    socket.send("我是客户端");
}
socket.onmessage = function(e){ // 监听客户端发来的信息
    console.log(e.data);
}
客户端和服务端可以开心的互相通信啦!
socket.io

socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,刚才是不是高兴的太早了而忘记了兼容性问题?没错socket.io就是帮你解决自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用!

安装socket.io模块

yarn add socket.io

通过socket.io建立链接

const express = require("express");
const app = express();
app.use(express.static(__dirname))
const server = require("http").createServer(app); // app本身就是监听函数
// socket 需要借助http服务
const io = require("socket.io")(server);
// 划分路径 /
io.of("/").on("connection",function(socket){
    console.log("链接成功")
    socket.on("message",function(msg){
        console.log(msg);
        socket.send("我是服务端");
    });
});
// 监听3000 端口
server.listen(3000);
// 默认会像浏览器中注入socket.io.js脚本

我们有了socket.io实现双向通信是不是很简单!

觉得本文对你有帮助吗?请分享给更多人

关注「前端优选」加星标,提升前端技能

关注公众号,获得更多前端高级技能
加我微信:webyouxuan

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/116361.html

相关文章

  • 你不知道WebSocket

    摘要:什么是是一种在单个连接上进行全双工通信的协议。短轮询配段代码,静态服务中间件用来返回静态文件当前价格是元获取最新价格接口客户端不停的发送请求,去服务端获取最新价格。它通过连接到一个服务器,以格式接收事件不关闭连接。 什么是WebSocket? WebSocket是一种在单个TCP连接上进行全双工通信的协议。这里我们发现了一个有趣的词:全双工,那我们就来简单了解下通信方式有哪些! 单工 ...

    remcarpediem 评论0 收藏0
  • Websocket解析及实现

    摘要:早期的轮询是通过不断自动刷新页面而实现的。长轮询的另一个问题是缺乏标准实现。服务器端接到这个请求后作出回应并不断更新连接状态以保证客户端和服务器端的连接不过期。协议解析协议包含两部分一部分是握手,一部分是数据传输。 Websocket是什么? Websocket是一个因为应用场景越来越复杂而提出的,针对浏览器和web服务器之间双向持续通信而设计,而且优雅地兼容HTTP的协议(我猜想:同...

    XboxYan 评论0 收藏0
  • 知道在springboot中如何使用WebSocket

    摘要:我们只需引入如下依赖即可注入首先注入一个该会自动注册使用注解申明的。 一、背景   我们都知道 http 协议只能浏览器单方面向服务器发起请求获得响应,服务器不能主动向浏览器推送消息。想要实现浏览器的主动推送有两种主流实现方式: 轮询:缺点很多,但是实现简单 websocket:在浏览器和服务器之间建立 tcp 连接,实现全双工通信   springboot 使用 websocket 有...

    selfimpr 评论0 收藏0
  • 基础知识 - 收藏集 - 掘金

    摘要:本文是面向前端小白的,大手子可以跳过,写的不好之处多多分钟搞定常用基础知识前端掘金基础智商划重点在实际开发中,已经非常普及了。 JavaScript字符串所有API全解密 - 掘金关于 我的博客:louis blog SF专栏:路易斯前端深度课 原文链接:JavaScript字符串所有API全解密 本文近 6k 字,读完需 10 分钟。 字符串作为基本的信息交流的桥梁,几乎被所有的编程...

    wdzgege 评论0 收藏0
  • python借助web3py与以太坊区块链节点交互的几种方式

    摘要:通信服务提供接口是如何与区块链交互的关键。这通常通过将请求提交给基于或套接字的服务器来完成。初始化时会发生自动检测有时,无法自动检测节点的位置。使用自动检测的示例一些节点提供超出标准的。是套接字的文件系统路径。 通信服务提供接口是web3如何与区块链交互的关键。接口接受JSON-RPC请求并返回响应。这通常通过将请求提交给基于HTTP或IPC套接字的服务器来完成。 如果你已经愉快地连接...

    booster 评论0 收藏0

发表评论

0条评论

techstay

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<