如何通过简单的Express API使用Websocket?

技术简介



Websocket是通过TCP连接的通信协议,旨在在浏览器和Web服务器之间实时交换消息。



为了建立WebSocket连接,客户端和服务器使用类似于HTTP的协议。客户端发出一个特殊的HTTP请求,服务器以特定的方式响应该HTTP请求。



备注



尽管新的请求和响应与HTTP请求和响应“相似”,但与之不同。例如,一个请求具有一个主体,但标头中没有“ Content-Length”字段(这违反了HTTP约定)。您可以在Wikipedia上阅读有关此内容的更多信息



该技术的主要优点之一是其简单性。客户端和服务器上只有4个事件要处理:



  1. 连接
  2. 错误
  3. 信息


为什么选择Websocket?



除ws外,还有两种其他的连续数据传输方法:服务器发送事件(SSE)和长轮询。



让我们比较一下服务器和客户端之间持续通信的机制,并得出有关使用Websocket为何值得(或不值得)的结论。



Websocket se 长池
协议 websocket(ws或wss) HTTP(S) HTTP(S)
速度
数据流的方向性 双向的 单向 双向的
另外 传输二进制数据,

不支持某些旧版浏览器
连接断开时自动重新连接


ws技术的主要优点之一是数据传输速度。SSE和LP使用HTTP(S)协议,工作方式如下:



  1. 要求更改;
  2. 如果服务器上出现更改,则服务器将其发送;
  3. , .


:



  1. .
  2. , HTTP(S).
  3. , .


api.



const http = require("http");
const express = require( "express");
const WebSocket = require( "ws");

const app = express();

const server = http.createServer(app);

const webSocketServer = new WebSocket.Server({ server });

webSocketServer.on('connection', ws => {
   ws.on('message', m => {
webSocketServer.clients.forEach(client => client.send(m));
   });

   ws.on("error", e => ws.send(e));

   ws.send('Hi there, I am a WebSocket server');
});

server.listen(8999, () => console.log("Server started"))


这里发生了什么?



要创建支持ws的服务器,我们创建一个常规的http服务器,然后在创建websocket时将其绑定到该服务器。



“开启”功能有助于管理websocket事件。最值得注意的事件是消息事件,因此让我们仔细看一下。



该函数在此处接收参数m-消息,即用户发送的消息。因此,我们可以从客户端发送一个字符串,并在服务器上对其进行处理。在这种情况下,服务器仅将此消息转发给连接到Websocket服务器的每个人。 webSocketServer对象的clients数组包含与服务器的所有连接。 ws对象一次仅存储一个连接。



评论



您不应该在实际的应用程序中使用这种方法。如果以这种方式描述api,则服务器无法将一个请求与另一个请求区分开。稍后将介绍如何构建基于websocket的api。



与客户端上的服务器的交互如下所示:



export const wsConnection = new WebSocket("ws://localhost:8999");
wsConnection.onopen = function() {
    alert(" .");
};

wsConnection.onclose = function(event) {
    if (event.wasClean) {
        alert('  ');
    } else {
        alert(' '); // , ""  
    }
    alert(': ' + event.code + ' : ' + event.reason);
};

wsConnection.onerror = function(error) {
    alert(" " + error.message);
};

export const wsSend = function(data) {
// readyState - true,   
    if(!wsConnection.readyState){
        setTimeout(function (){
            wsSend(data);
        },100);
    } else {
        wsConnection.send(data);
    }
};


基于Websocket的API



与REST API的请求分布在不同的URL上不同,Websocket API仅具有一个URL。为了构建基于websocket的完整API,您需要教系统将一个请求与另一个请求区分开。这可以实现如下:



1)从客户端,我们将以json字符串的形式传输请求,并在服务器上进行解析:



const sendMessage = (message) => conn.send(JSON.stringify({ event: "chat-message", payload: { userName, message }}));


2)在服务器上,我们解析字符串,然后选择事件字段-请求的类型。让我们为每种类型写下相应的答案:



const dispatchEvent = (message, ws) => {
   const json = JSON.parse(message);
   switch (json.event) {
       case "chat-message": webSocketServer.clients.forEach(client => client.send(message));
       default: ws.send((new Error("Wrong query")).message);
   }
}


因此,我们可以将不同的请求发送到服务器,并根据请求处理响应。



结论



如果您承担了制作API的任务,并且发现客户对支持旧版浏览器不感兴趣,那么基于WebSocket的API是一个不错的选择。为了您的方便,我们在link上为客户端和服务器部分准备了代码



All Articles