开发设计VUE

简易WebSocket

2019-07-23  本文已影响187人  开心人开发世界

这是我将要编写的WebSocket系列的第一篇文章,其目标是以最简单的方式解释事物。让我们直接进入它。

WebSockets允许用户使用持久的双向连接向服务器发送和接收消息。基本上,这是客户端服务器之间的通信方式。让我们先了解一下这种通信,稍后我们将回到WebSockets。

客户端和服务器

Web浏览器(客户端)和服务器通过TCP/IP进行通信。超文本传输​​协议(HTTP)是TCP/IP 之上的标准应用程序协议支持请求(来自Web浏览器)及其响应(来自服务器)。

这是如何运作的?

我们来看看这些简单的步骤: -

  1. 客户端向服务器发送请求。
  2. 建立连接。
  3. 服务器发回响应。
  4. 客户端收到响应。
  5. 连接已关闭。

这是对客户端和服务器之间标准通信如何工作的简单概述。现在仔细看看第一步。5。

连接已关闭。

HTTP请求已达到其目的,不再需要它,因此连接已关闭。

如果服务器想要向客户端发送消息,该怎么办?

在我们的标准请求/响应方案中,必须根据开始通信的请求建立连接。如果服务器想要发送消息,则客户端必须发送另一个请求以建立连接并接收消息。

客户端如何知道服务器想要发送消息?

考虑这个例子:
客户饿了,并在网上订购了一些食物。他每秒发出一个请求以检查订单是否准备就绪。

0秒:食物准备好了吗?(客户)
0秒:不,等等。(服务器)
1秒:食物准备好了吗?(客户)
1秒:不,等等。(服务器)
2秒:食物准备好了吗?(客户)
2秒:不,等等。(服务器)
3秒:食物准备好了吗?(客户)
3秒:是的,先生,这是您的订单。(服务器)

这就是你所谓的HTTP轮询。客户端向服务器发出重复请求,并检查是否有任何消息要接收。

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

有没有办法克服这个问题

是的,有一种用于克服这种缺陷的轮询技术,它被称为长轮询(Long Polling)。

Long Polling基本上涉及向服务器发出HTTP请求,然后保持连接打开以允许服务器稍后响应(由服务器确定)。

考虑上面例子的Long-Polling版本: -

0秒:食物准备好了吗?(客户)
3秒:是的,先生,这是您的订单。(服务器)

这样,问题解决了。
不完全是。虽然长轮询工作,但它在CPU,内存和带宽方面非常昂贵(因为我们阻止资源保持连接打开)。

我们现在干什么?看起来事情已经失控。让我们回到我们的救世主:WebSocket

为什么选择WebSockets

如您所见,Polling和Long-Polling都是非常昂贵的选项,以模拟客户端和服务器之间的实时通信。此性能瓶颈是您希望使用WebSocket的原因。

WebSockets不需要您发送请求以进行响应。它们允许双向数据流,因此您只需要监听任何数据。

您可以只听服务器,它会在可用时向您发送消息。

让我们看一下WebSocket的性能方面。

资源消耗

下图显示了一个相对常见的用例中WebSockets与Long Polling之间的带宽消耗差异:

差异很大,并且随着请求的数量呈指数增长。

速度

以下是在一秒内为每个连接提供的1,10和50个请求的结果:

如您所见,使用Socket.io对每个连接发出单个请求的速度要慢50%,因为必须首先建立连接。这种开销较小,但对于十个请求仍然很明显。在来自同一连接的50个请求中,Socket.io已经快50%。为了更好地了解峰值吞吐量,我们将查看基准测试,每个连接的请求数量更多(500,1000和2000):

在这里,您可以看到HTTP基准峰值约为每秒约950个请求,而Socket.io每秒约为3900个请求。有效,对吗?

注意:Socket.io是用于实时Web应用程序的JavaScript库。它在内部实现WebSocket。将此视为WebSocket的包装器,它提供了更多功能(本系列的下一篇博客文章详细介绍了Socket.io

WebSockets如何工作

这些是建立WebSocket连接所涉及的步骤。

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

我们将创建两个文件:一个服务器和一个客户端。
首先,创建一个<html>名为client.html包含<script>标记的简单文档。让我们看看它的外观: -

Client.html

<html>

<script>
    // Our code goes here
</script>

<body>
    <h1>This is a client page</h1>
</body>

</html>

Server.js

现在创建另一个文件server.js。导入HTTP模块并创建服务器。让它听port 8000

这将作为一个简单的http服务器监听port 8000。让我们看一下:

//importing http module
const http = require('http');

//creating a http server
const server = http.createServer((req, res) => {
    res.end("I am connected");
});

//making it listen to port 8000
server.listen(8000);

运行命令node server.js开始监听port 8000您可以根据需要选择任何端口,我只是选择了8000无特殊原因。

我们现在完成了客户端和服务器的基本设置。那很简单,对吧?让我们现在就开始吧。

客户端设置

要构造WebSocket,请使用WebSocket()返回websocket对象的构造函数。此对象提供用于创建和管理与服务器的WebSocket连接的API 。

简单来说,这个websocket对象将帮助我们建立与服务器的连接并创建双向数据流,即从两端发送和接收数据

让我们看看如何:

<html>

<script>
    //calling the constructor which gives us the websocket object: ws
    let ws = new WebSocket('url'); 
</script>

<body>
    <h1>This is a client page</h1>
</body>

</html>
      

WebSocket构造函数需要一个URL来听。在我们的例子中,这是'ws://localhost:8000'因为我们的服务器正在运行。
现在,这可能与您习惯的有点不同。我们没有使用HTTP协议,我们正在使用WebSocket协议。这会告诉客户“嘿,我们使用WebSocket协议”,因此'ws://'代替'http://'。够简单吗?现在让我们实际创建一个WebSocket服务器server.js

服务器设置

我们将ws在节点服务器中使用第三方模块来使用和设置WebSocket服务器。

首先,我们将导入ws模块。然后我们将创建一个websocket服务器并将其HTTP交给服务器监听port 8000

HTTP服务器正在侦听端口8000,WebSocket服务器正在侦听此HTTP服务器。基本上,这就是监听者。

现在我们的websocket正在关注流量port 8000。这意味着它将在客户端可用时立即尝试建立连接。我们的server.js文件看起来像这样:

const http = require('http');
//importing ws module
const websocket = require('ws');

const server = http.createServer((req, res) => {
    res.end("I am connected");
});
//creating websocket server
const wss = new websocket.Server({ server });

server.listen(8000);

正如我们之前讨论的那样 - WebSocket()构造函数返回一个websocket对象,提供用于创建和管理与服务器的WebSocket连接的API 。

在这里,wss对象将帮助我们Event在某些事情发生时听取发出的声音。就像建立连接或握手完成或连接关闭等。

让我们看看如何收听消息:

const http = require('http');
const websocket = require('ws');

const server = http.createServer((req, res) => {
    res.end("I am connected");
});
const wss = new websocket.Server({ server });
//calling a method 'on' which is available on websocket object
wss.on('headers', (headers, req) => {
    //logging the header
    console.log(headers);
});

server.listen(8000);

该方法'on'需要两个参数:事件名称和回调。事件名称是我们想要监听/发出的,回调指定了如何处理它。在这里,我们只是记录headers事件。让我们看看我们得到了什么:

这是我们的HTTP标题,我希望你对它好奇,因为这正是幕后发生的事情。让我们分解它以更好地理解它。

现在这将更有意义。

Headers响应标头被写入到插座作为握手的一部分之前被发射事件。这允许您在发送标头之前检查/修改标头。这意味着您可以根据需要修改标题以接受,拒绝或其他任何内容。默认情况下,它接受请求。

同样,我们可以添加一个connection在握手完成时发出的事件。成功建立连接后,我们将向客户端发送消息。我们来看看如何:

const http = require('http');
const websocket = require('ws');

const server = http.createServer((req, res) => {
    res.end("I am connected");
});
const wss = new websocket.Server({ server });

wss.on('headers', (headers, req) => {
    //console.log(headers); Not logging the header anymore
});

//Event: 'connection'
wss.on('connection', (ws, req) => {
    ws.send('This is a message from server, connection is established');
    //receive the message from client on Event: 'message'
    ws.on('message', (msg) => {
        console.log(msg);
    });
});

server.listen(8000);

我们也在听取message客户的意见。让我们创造: -

<html>

<script>
    let ws = new WebSocket('url'); 
    //logging the websocket property properties
    console.log(ws);
    //sending a message when connection opens
    ws.onopen = (event) => ws.send("This is a message from client");
    //receiving the message from server
    ws.onmessage = (message) => console.log(message);
</script>

<body>
    <h1>This is a client page</h1>
</body>

</html>

这就是它在浏览器中的外观: -

第一个日志WebSocket列出了websocket对象上的所有属性,第二个日志列出MessageEventdata属性。如果仔细观察,您会看到我们从服务器收到了消息。

服务器日志将如下所示:

我们正确地收到了客户的消息。这标志着我们的连接成功建立。干杯吧!

结论

总结一下,让我们来看看我们学到的东西:

这是WebSockets的基础知识及其工作原理。本系列的下一篇文章socket.io将更详细地介绍和使用它。我们还将看到为什么socket.io当事情与唯一的本地人一起工作时我们确切需要WebSocket()。当我们成功发送和接收消息时,为什么要使用臃肿的库?

如果您觉得它有用,请分享这篇文章并继续关注下一篇文章。
沙德。

参考

转:https://levelup.gitconnected.com/websocket-simplified-b532f266cc9f

上一篇下一篇

猜你喜欢

热点阅读