专栏首页WebJ2EE【NPM库】- 0x06 - WebSocket

【NPM库】- 0x06 - WebSocket

目录
1. WebSocket
  1.1. 是什么?
  1.2. 一个例子
  1.3. 连接建立过程
2. ws
  2.1. 基础
  2.2. 简易 Server
  2.3. 复用 HTTP 连接
3. webpack-dev-server 对 WebSocket 的应用
  3.1. 总体结构
  3.2. WebSocket 后端
  3.3. WebSocket 前端

1. WebSocket

1.1. 是什么?

WebSocket 是一种通信协议,可在单个 TCP 连接上进行全双工通信。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以建立持久性的连接,并进行双向数据传输。

  • 握手阶段采用 HTTP 协议
  • 数据格式轻量,性能开销小(HTTP每次都需要携带完整头部)
    • 服务端到客户端的数据包头只有2到10字节。
    • 客户端到服务端需要加上另外4字节的掩码。
  • 更好的二进制支持
    • 可以发送文本、二进制数据
  • 没有同源限制,客户端可以与任意服务器通信
  • 协议标识符是ws(如果加密,则是wss)

1.2. 一个例子

效果展示:

后端代码:

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 8080 });

wss.on('connection', function connection(ws) {
    ws.on('message', function incoming(message) {
        console.log('received: %s', message);
        ws.send(`echo: ${message}!`);
    });

    ws.send('connected!');
});

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style type="text/css">
    .websocket {
      width: 800px;
      border: 1px solid #ccc;
      margin: 16px auto 0 auto;

      display: flex;
      flex-direction: row;
    }
    .websocket p {
      text-align: center;
    }

    .websocket > .send {
      flex: 1;
      padding: 16px;
      border-right: 1px solid #ccc;
    }
    .websocket > .send > .msg-send{
      width: 100%;
      height: 200px;
      border-radius: 5px;
    }
    .websocket > .send .btn-send {
      border: none;
      border-radius: 5px;
      background: #25d1ff;
      padding: 5px 10px;
      color: #fff;
      cursor: pointer;
    }
    .websocket > .send .btn-close {
      border: 1px solid #ccc;
      border-radius: 5px;
      background: none;
      padding: 5px 10px;
      cursor: pointer;
    }


    .websocket > .receive {
      flex: 1;
      padding: 16px;
    }
    .websocket > .receive > .msg-receive {
      height: 200px;
      border: 1px solid #ccc;
      border-radius: 5px;
      overflow: auto;
    }
    .websocket > .receive > .msg-receive > .msg-item{
      font-size: 14px;
    }
</style>
</head>
<body>
  <div class="websocket">
    <div class="send">
      <p>数据发送</p>
      <textarea type="text" class="msg-send"></textarea>
      <p>
        <button class="btn-send">发送消息</button>
        <button class="btn-close">关闭连接</button>
      </p>
    </div>
    <div class="receive">
      <p>数据接收</p>
      <div class="msg-receive"></div>
    </div>
  </div>

  <script type="text/javascript">
    const ws = new WebSocket('ws://127.0.0.1:8080');
    ws.onopen = e => {
      console.log(`WebSocket 连接状态:${ws.readyState}`)
    };
    ws.onmessage = data => {
      const msgReceive = document.querySelector('.websocket > .receive > .msg-receive');
      msgReceive.innerHTML += `<div class="msg-item">${data.data}</div>`;
    };
    ws.onclose = data => {
      console.log('WebSocket连接已关闭')
      console.log(data);
    };

    // 发送消息
    const btnSend = document.querySelector('.websocket > .send .btn-send');
    const msgSend = document.querySelector('.websocket > .send > .msg-send');
    btnSend.onclick = () => ws.send(msgSend.value);

    // 关闭链接
    const btnClose = document.querySelector('.websocket > .send .btn-close');
    btnClose.onclick = () => ws.close();
</script>
</body>
</html>

1.3. 连接建立过程

  1. 客户端发起HTTP握手,告诉服务端进行WebSocket协议通讯,并告知WebSocket协议版本。
  2. 服务端确认协议版本,升级为WebSocket协议。
  3. 之后如果有数据需要推送,会主动推送给客户端。

请求字段重点包括:

  • Connection: Upgrade,表示请求升级协议
  • Upgrade: websocket,表示请求升级到 websocket 协议
  • Sec-WebSocket-Version,表示 websocket 的版本。
    • 如果服务端不支持该版本,需要返回一个Sec-WebSocket-Versionheader,里面包含服务端支持的版本号。
  • Sec-WebSocket-Key,对应服务端响应头的Sec-WebSocket-Accept,由于没有同源限制,websocket 客户端可任意连接支持websocket的服务。这个就相当于一个钥匙一把锁,避免多余的,无意义的连接。

响应字段重点包括:

  • Sec-WebSocket-Accept:用来告知服务器愿意发起一个 websocket 连接, 值根据客户端请求头的 Sec-WebSocket-Key 计算出来。

2. ws

2.1. 基础

  • ws is a simple to use, blazing fast, and thoroughly tested WebSocket client and server implementation.

2.2. 简易 Server

const WebSocket = require('ws');
 
const ws = new WebSocket('ws://www.host.com/path');
 
ws.on('open', function open() {
  const array = new Float32Array(5);
 
  for (var i = 0; i < array.length; ++i) {
    array[i] = i / 2;
  }
 
  ws.send(array);
});

2.3. 复用 HTTP 连接

  • Multiple servers sharing a single HTTP/S server
const http = require('http');
const WebSocket = require('ws');
const url = require('url');
 
const server = http.createServer();
const wss1 = new WebSocket.Server({ noServer: true });
const wss2 = new WebSocket.Server({ noServer: true });
 
wss1.on('connection', function connection(ws) {
  // ...
});
 
wss2.on('connection', function connection(ws) {
  // ...
});
 
server.on('upgrade', function upgrade(request, socket, head) {
  const pathname = url.parse(request.url).pathname;
 
  if (pathname === '/foo') {
    wss1.handleUpgrade(request, socket, head, function done(ws) {
      wss1.emit('connection', ws, request);
    });
  } else if (pathname === '/bar') {
    wss2.handleUpgrade(request, socket, head, function done(ws) {
      wss2.emit('connection', ws, request);
    });
  } else {
    socket.destroy();
  }
});
 
server.listen(8080);

3. webpack-dev-server 对 WebSocket 的应用

3.1. 总体结构

3.2. WebSocket 后端

  • webpack-dev-server 的 WebSocket 通信默认采用 sockjs 实现。
    • 可通过 transportMode 属性进行调整。
  • webpack-dev-server 复用提供 Web 服务的 Server。
    • sockjs-node 是默认的 websocket 服务访问路径。
      • 可通过 devServer.sockPath 属性自行定制。

webpack-dev-server 的 CLI 入口:

webpack-dev-server 如何选择 WebSocket 的 Server 端实现:

webpack-dev-server 如何确定 WebSocket 的服务地址:

3.3. WebSocket 前端

  • webpack-dev-server 的 WebSocket 通信默认采用 sockjs 实现。
    • 可通过 transportMode 属性进行调整。
  • webpack-dev-server 的 WebSocket 前端,是作为一个入口,自动注入到应用系统中的。

webpack-dev-server 的 WebSocket 前端实现何时选定?:

webpack-dev-server 的 WebSocket 前端实现何时选定?:

webpack-dev-server 的 WebSocket 前端如何加载?:

参考:

ws: https://github.com/websockets/ws webpack-dev-server: https://www.webpackjs.com/configuration/dev-server/ webpack-dev-server 配置: https://webpack.js.org/configuration/dev-server/#devserversockpath https://webpack.js.org/configuration/dev-server/#devservertransportmode


本文分享自微信公众号 - WebJ2EE(WebJ2EE),作者:WEBJ2EE

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-08-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【React】:Refs

    Refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。

    WEBJ2EE
  • WEB:字符集、编码、乱码 —— 看这篇就够了

    ASCII(美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语,是现今最通用的单字节编码系统。

    WEBJ2EE
  • 设计模式——状态模式

    有限状态机(Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型...

    WEBJ2EE
  • Java 反序列化工具 gadgetinspector 初窥 (上)

    一开始是听@Badcode师傅说的这个工具,在Black Hat 2018的一个议题提出来的。这是一个基于字节码静态分析的、利用已知技巧自动查找从source到...

    Seebug漏洞平台
  • Sentinel控制台实时监控【源码笔记

    从控制台监控来看,可以看出时间戳、通过QPS、拒绝的QPS、响应时间以及相应的波动曲线,接下来分析这些数据怎么来的?

    瓜农老梁
  • php用select实现I/O复用

    在Linux Socket服务器短编程时,为了处理大量客户的连接请求,需要使用非阻塞I/O和复用,select、poll和epoll是Linux API提供的I...

    gaobinzhan
  • 如何做旅游小程序项目,开发旅游小程序的价值有哪些?

    随着社会的发展,旅游业已成为全球经济中发展势头最强劲和规模最大的产业之一.旅游业在城市经济发展中的产业地位、经济作用逐步增强,旅游业对城市经济的拉动性、社会就业...

    速成应用小程序开发平台
  • antd3.x中的form

    最近在维护公司的中台erp系统,项目中js库用的是react,ui库用的是antd。平时还是喜欢自己写css,刚开始还是有点不太习惯直接上ui库做项目,觉得用a...

    _kyle
  • Flutter 事件机制 - Future 和 MicroTask 全解析

    了解过Flutter的同学都知道,不同于 Android 原生开发,dart 是单线程实体的语言,所以我们一般的异步操作,实际上还是通过单线程通过调度任务优先级...

    Android技术干货分享
  • 早报:人工智能程序可1秒检测出肠癌 准确率86%

    1、人工智能程序可1秒检测出肠癌 准确率86% 【网易智能讯 10月31日消息】为了更准确地检测癌症,这一研究已取得了巨大的进步。一项来自日本横滨的研究发现,...

    用户1335017

扫码关注云+社区

领取腾讯云代金券