Loading [MathJax]/jax/output/CommonHTML/jax.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >WebSocket 初识篇

WebSocket 初识篇

原创
作者头像
溪歪歪
修改于 2020-08-27 10:00:15
修改于 2020-08-27 10:00:15
2K40
代码可运行
举报
文章被收录于专栏:巫山跬步巫山跬步
运行总次数:0
代码可运行

本文将基于腾讯云Lighthouse(轻量应用服务器)实例,对WebSocket进行简单的示例演示,以及初步的协议原理探索。帮助大家直观地感受双向通讯的特点以及常见的基于JavaScript的实现方法。

0x00 背景概念

WebSocket是近些年适用广泛且流行的网络传输协议,它使得在Web等HTTP协议的应用场景中,可以非常方便地实现类似TCP的全双工通信。这种建立在一个持久连接之上的基于消息的双向通信机制,相比HTTP的Request-Response的事务请求模式,可以让客户端与服务器端的通讯变得丰富和灵活。

WebSocket协议在2011年由IETF组织标准化为RFC6455,浏览器的WebSocket API由W3C标准化被各大主流浏览器全面支持。目前WebSocket已是服务器端向客户端推送数据等功能的标准协议,在站内信、聊天室、新闻推送、视频弹幕发送等多种场景下应用广泛。

0x01 示例目标

首先,那么让我们直观感受一下什么是全双工通信的协议。简单说就是在通讯双方可以在任意时刻,根据自身状态向对端发送数据。而不是受限于发送请求/超时前返回等类似HTTP的精简固定模式,就像一直在握着手交谈。

如下图所知,描述了客户端和服务器的一次连接及通信过程。可以看出客户端通过不断探索试探以及根据服务器端的返回,完成了和服务器端友好的“相互沟通”,而非直接地一问一答。

接下来,我们将用最精简的WebSocketAPI以及服务端代码实现类似的功能。

0x02 环境准备

工欲善其事,必先利其器。选择一台计算/网络性能强劲且操作简易的云服务器是上路体验的第一步。

目前腾讯云最流行的IaaS级产品莫过于Lighthouse(轻量应用服务器)了。该产品以套餐形式提供了便捷的云主机选购,网络流量包、应用镜像以及免密登录等特性也更加注重了人性化的体验。Lighthouse作为目前最炙手可热的面向个人开发者及中小企业的新一代云服务器产品,特别适合搭建个人博客、网站、论坛、小型应用等多种场景。另外,其良心的价格和促销力度也是前所未有,其持续运营的策略是相对面向未来的。总之,如果需要一台CVM(云服务器),可以考虑先使用Lighthouse。

详细的产品介绍可以参考这里:Lighthouse产品介绍,点击前往 购买传送门,如下图所示:

可以看到,Lighthouse整个购买页只有这一页,步骤也很清晰明确,仅仅需要关注选择镜像和套餐就足够了。

当然也有另一种选择,用Ubuntu/CenteOS等系统镜像,那就需要安装Node.js,其实过程也不复杂。官网下载Node.js最新的x64二进制预编译包,解压到/usr/local目录即可:

代码语言:shell
AI代码解释
复制
sudo tar -C /usr/local --strip-components=1 -Jxvf node-v12.18.3-linux-x64.tar.xz

Lighthouse的“套餐”其实是对CPU/内存/网络的流量带宽等基础资源“打包”的概念,通常根据需要选择即可。对于本文的实验选择最简单的套餐也足够。

然后打开咱们最顺手的JavaScript语言编辑器,准备开始下一步吧。

0x03 代码演示

本节我们正式讲解浏览器端WebSocketAPI,以及服务器端Node.js实现的基本方法。

客户端实现

浏览器端两个简单的html/js文件即可:

代码语言:shell
AI代码解释
复制
➜  websocket-example git:(master) ✗ tree client 
client
├── index.html
└── index.js

index.js内容如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const uri = 'ws://' + location.host + ':3000/'
const socket = new WebSocket(uri)

socket.addEventListener('message', (event) => {
  try {
    let data = JSON.parse(event.data)
    console.log(`TA说: “${data.content}`)
    if (data.detail) console.log('详情: ', data.detail)
  } catch(e) {
    console.log(e)
  }
})

socket.addEventListener('open', (event) => {
  socket.send(JSON.stringify({ 'content': '我来了' }))
})

socket.addEventListener('close', (event) => {
  console.log('被拒绝了。')
})

function say(content, detail) {
  socket.send(JSON.stringify({ 'content': content, 'detail': detail }))
}

我们通过WebSocket()函数初始化和服务器的连接,实例化到WebSocket对象(socket)。然后只需实现并注册监听器事件函数即可,就如同一般的DOM对象事件处理类似。这里统一用了addEventListener函数,也可以用更简洁的onopen()onclose()onmessage()方法来实现连接建立、连接断开以及有数据消息到达的处理函数。相关API的详细介绍可以参考MDN的文档

注意:此处仅做和示例演示,忽略了错误处理onerror(),真实场景中应该妥善处理错误(如连接被服务器断开等),或者用封装更全面的WebSocket客户端库。

另外,注意到我们在连接建立时主动向服务器端发送了第一条消息。而且我们还实现了一个say()方法向服务器端发送消息,后续将用其在console中直接调用。

页面结构我们这里用最简单的元素,加载上述脚本即可(关于页面设计超出非本文范围,后续会有篇幅专门介绍)。

代码语言:html
AI代码解释
复制
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>websocket example</title>
</head>
<body>
  <p>websocket example</p>
  <script src="index.js"></script>
</body>
</html>

运行(serve)客户端静态代码有很多方式,比如常见的Nginx即可,这里我们用npm下的http-server工具,更加方便。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install -g http-server
http-server -p 80 client

运行结果

打开console,我们来试试验证下和服务器“通话”。

愉快的对话:

尬聊的对话:

服务端实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const WebSocket = require('ws')

const wsServer = new WebSocket.Server({ port: 3000 })
// client session state
const wsClients = {}

wsServer.on('connection', (ws, req) => {
  let clientId = req.headers['sec-websocket-key']
  console.log(`client ${clientId} connected.`)
  wsClients[clientId] = { '状态': '无聊', '兴奋度': 0 }  // 状态枚举:'无聊', '起兴', '热情'

  ws.on('message', (message) => {
    message = JSON.parse(message)
    handle(ws, message, wsClients[clientId])
  })

  ws.on('close', (message) => {
    console.log(`client ${clientId} closed.`)
    delete wsClients[clientId]
  })
})

// handle message of the specific client and emit
function handle(ws, message, state) {
  console.log(message.content)
  let shouldClose = false
  let content = ''
  let detail = null
  switch (state['状态']) {
    case '无聊':
      switch (message.content) {
        case '我来了': content = '才来啊'; break
        case '路上堵': state['状态'] = '起兴'; content = '喝点啥'; detail = Beverage; break
        default: content = '呵呵'; shouldClose = true; break
      }; break
    case '起兴':
      switch (message.content) {
        case '我看看': content = '一般般'; break
        case '再来不': content = '不错哦'; state['兴奋度'] = state['兴奋度'] + 1; break
        case '听我的':
          if (state['兴奋度'] >= 2) { state['状态'] = '热情'; content = '随你哦'; detail = '<已解锁>' }
          else { content = '呵呵'; shouldClose = true }
          break
        default: content = '呵呵'; shouldClose = true; break
      }
      break
    case '热情':
      try {
        content = eval(message.content)
      } catch (e) {
        content = '呵呵'; shouldClose = true
      }
      break
    default: content = '呵呵'; shouldClose = true; break
  }
  ws.send(JSON.stringify({ 'content': content, 'detail': detail }))
  if (shouldClose) ws.close()	// 无话可说, 主动告辞
}

const Beverage = [
  'Cosmopolitan', 'Daiquiri', 'Negroni', 'Mojito', 'Old fashion', 'Screwdriver', 'Tequila Sunrise', 'Whiskey Sour'
]

WebSocket的服务端逻辑代码理论上可以用任何编程语言实现,这里我们采用最方便的Node.js(ws库)来实现。

服务器端代码看起来很客户端有不少相似出,比如也是通过实现WebSocket连接对象的事件监听器函数来实现功能。

不同的是:

  • 后台需要记录和每一个客户端连接的信息状态,这里通过sec-websocket-key来作为ID标识一个客户端并记录在全局的字典中;
  • 服务器端通常有更多状态记录,并根据和每个客户端的不同阶段动态计算返回,这也是最用的思路。(其实上一节的客户端本质也有这个环节,只不过通过人脑来手工完成了。)

这种类似“解析+检索+计算+返回”模式很直接,通常Switch语句实现即可,看其来很类似一些解析协议的C代码,是不是很熟悉?当然更现代的语言有一些更方便的语法如pattern-matching等,但逻辑一样,因为本质就是实现一个有限状态机(见下节)。

相信机智的你已经读懂服务器端的逻辑了,应该不会出现“聊天止于呵呵”的场景了。

0x04 分析小结

那么现在我们分析示例代码后,相信你对单个连接建立后的双向全双工通信实现有了基本的认识,即通信双方均只需要实现一个针对业务的有限状态机——具体说是确定性有限自动机(DFA):

有限状态机计算模型图示:

或者比较流行的基于MPSC的ActorModel:

而我们的主角——WebSocket(以及相关API和库)只是担任通信的底层协议和部分实现媒介。

至此我们示例讲解结束,下面开始我们从握手过程开始,逐渐探索WebSocket协议原理。

0x05 协议原理

握手过程

首先我们来分析下WebSocket建立连接即握手的过程。受益于通过HTTP的Upgrade请求(升级协商),只需要经过一次RTT即可客户端和服务器端的连接。可以用Linux下的nc命令来具体查看握手细节如图:

如红色框标识所示,如果向WebSocket服务器发送普通的HTTP请求,会收到服务器端返回的426错误,表示需要客户端升级协议。

如绿色框所示是成功建立连接的情况:

客户端需要请求时至少带上5个特定的请求头(Header):ConnectionHostUpgradeSec-WebSocket-Version以及Sec-WebSocket-Key。前四个是固定值,最后一个Key由客户端提供,用来向服务器确认客户端有权升级请求到WebSocket协议。不安全的客户端希望升级时,用此Header可以某种程度上的保护以防止滥用或无意间地请求升级,Key值是规范中定义的方法计算的因而不能提供任何安全性。 总之这个Key是用来“明确确认”客户端的确希望升到WebSocket协议。另外,该Key每个连接特定的值,16字节的随机数的Base64编码,可以看成是每个WebSocket连接的“ID”。另外,浏览器客户端通常还会发送Origin请求头,配合服务器端实现相关的CORS策略。

服务器端则需要返回101状态码,明确告知客户端连接协议已经切换为WebSocket协议,并返回UpgradeConnectionSec-WebSocket-AcceptHeadher,注意后者是根据客户端的Key通过固定方法hash出来的。

连接建立后,两端的双方即可发送消息了,接下来我们一起来认识下帧结构。

协议帧结构

从我们刚才的示例代码可以看出,WebSocket的API是面向消息(message-oriented)的,即一端发送任意的UTF-8编码或二进制的文本,另一端只有在整个消息全部发送完成时,才会触发上层的事件通知。而整个分帧的逻辑细节,对与协议使用者是无感知的。WebSocket采用独特的二进制分帧格式,将每一条应用消息分拆为多个数据帧(frames),并传输至对端、重组消息以及通知。

帧是指最小的通信单元,每帧由变长的帧头和一个净荷数据(payload)组成,承载整条或部分应用消息;而消息本质是可以映射到一条应用逻辑消息的完整的帧序列。

帧格式如下图:

包括FIN、Opcode、Mask、Length、Masking Key以及Payload。FIN标记是否为最后一帧,Opcode包含帧类型的说明(数据帧中的Text/Binary标志)或者控制帧的类型(close/ping/pong等),Payload是数据部分,Mask Key是用来说明payload的掩码。注意Length(Payload长度)本身也是变长的字段。

0x06 协议对比

功能特性

WebSocket提供一种低延迟双向发送二进制/文本应用消息的机制。另外它的设计使得其带宽消耗少,因为只有建立连接时带少量头部信息。相比基于HTTP的XHR polling以及EventSource的Streaming都有很大的优势。因而更适合服务器主动向客户端推送的场景。

与HTTP/TCP关系

WebSocket的设计哲学中提到希望最小化分帧,仅有分帧只是让协议是基于帧(而非基于流)的,并支持区分Unicode文本和二进制帧。从而实现面向消息的协议。元数据的处理应该被设计在WebSocket之上的应用协议中来完成,就如同TCP上的应用协议(如HTTP)处理元数据的方式。

  • vs. TCP: 概念上,WebSocket只是TCP之上的一个协议,多做了如下的工作: 针对浏览器作了一个基于origin Header的安全模型 一个用于寻址和协议的名字空间机制,使得一个IP上可以有多个主机名,以及一个端口上可有多个WebSocket服务 在TCP上加了一个分帧的机制,类似IP网络包的分帧,而且不限长度。 增加了断开连接(挥手)机制,可以更好地适配已有的网络中间层服务如代理服务。 另外,它被设计成可以和HTTP服务器共享端口,并通过HTTP Upgrade请求来建立握手连接,这使得它也可以很简单方便地与已有的HTTP基础服务共存,如已有的缓存服务、安全策略等等。
  • vs. HTTP: WebSocket协议是一个独立的基于TCP的协议。它和HTTP唯一的关系就是它的握手(建立连接)是由HTTP服务器作为升级请求进而处理完成的。 默认情况下,WebSocket协议用80端口作为普通连接,用443端口作为TLS连接。 比HTTP强的地方主要在并发性能,HTTP是Request-Responde事务型的,而WebSocket一个连接可以发很多请求。即便HTTP/2以后也可以,但由于HTTP被设计成短期爆式的连接会断/以及客户端连接数的限制,而WebSocket是长时间的连接,没有这个限制。相比HTTP1.1的keep-alive连接,虽然一次TCP连接中可以发多个请求,但是仍受限于Request-Response模式,并且每个Request仍然要带上请求头。

0x07 最佳实践

任何协议的应用都需要考虑性能和安全两大因素,WebSocket也不例外,这里简单介绍几个最佳实践Tips。

首先,因为WebSocket是面向消息的,在一个连接内,第一个消息没有发送完成时,是无法发送第二个消息的,中间仅能插入控制帧。因此我们的消息设计要尽可能小一些,(对于大消息尽量拆分来避免head-of-line阻塞)或者高效利用压缩机制。另外,WebSocket天生可以利用HTTP已有的技术设施,比如浏览器和中介(Intermediary)如代理、CDN服务器的缓存,利用好这些也能明显提速。最后,安全上除了origin请求头以外,尽量采用WSS协议(WebSocket over TLS)来增加安全性、完整性和身份认证

0x08 总结展望

看到这里,相信你已经对WebSocket协议/API有了直观的了解,熟悉其原理和部分最佳实践,明确了典型的应用场景。最重要的,体验了双向协议的常规编程实现方法。下一步或许可以尝试着自己写一些有趣的应用了。

不过,对于部署真实的WebSocket应用来说,还有很多实操性较强的问题需要解决,比如配置反向代理、多节点连接保持、高可用地发送消息等等。我们后续将陆续为大家介绍相关知识点和实践案例,敬请期待~

0x09 参考资料

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
4 条评论
热度
最新
专业专业!条理清晰易懂~这个标题编码方式也好有趣哈哈哈
专业专业!条理清晰易懂~这个标题编码方式也好有趣哈哈哈
回复回复点赞举报
简单易懂,又有一定实践内容与深度,深入浅出,赞
简单易懂,又有一定实践内容与深度,深入浅出,赞
回复回复点赞举报
感谢分享!可以讲下在Nginx或云上环境的最佳实践麻
感谢分享!可以讲下在Nginx或云上环境的最佳实践麻
回复回复点赞举报
坐沙发~ 生动有趣!小白看得津津有味?
坐沙发~ 生动有趣!小白看得津津有味?
回复回复点赞举报
推荐阅读
编辑精选文章
换一批
webSocket和EventSource的区别
WebSocket和EventSource是两种在Web应用程序中用于实现实时通信的不同技术。WebSocket是一种双向通信协议,允许服务器与客户端建立持久性连接并通过该连接发送消息。而EventSource是一种服务器推送技术,只允许服务器向客户端发送消息,而不允许客户端向服务器发送消息。 在下面的描述中,我将详细介绍WebSocket和EventSource的不同之处,并提供一些代码示例。
世间万物皆对象
2024/03/20
4180
you-dont-know-websocket
本文阿宝哥将从多个方面入手,全方位带你一起探索 WebSocket 技术。阅读完本文,你将了解以下内容:
阿宝哥
2020/07/29
1.8K0
you-dont-know-websocket
WebSocket 全面解析+实战演练(Nodejs实现简易聊天室)
WebSocket是一种在单个TCP连接上提供全双工通信能力的协议。简单来说,它允许客户端和服务器互相推送数据,无需重复建立连接,大大提升了交互效率和实时性🚀。
空白诗
2024/06/14
3960
WebSocket 全面解析+实战演练(Nodejs实现简易聊天室)
WebSocket 原理浅析与实现简单聊天
随着 Web 的发展,用户对于 Web 的实时推送要求也越来越高,在 WebSocket 出现之前,大多数情况下是通过客户端发起轮询来拿到服务端实时更新的数据,因为 HTTP1.x 协议有一个缺陷就是通信只能由客户端发起,服务端没法主动给客户端推送。
用户4962466
2019/12/12
7660
.NET Core 基于Websocket的在线聊天室
我们在传统的客户端程序要实现实时双工通讯第一想到的技术就是socket通讯,但是在web体系是用不了socket通讯技术的,因为http被设计成无状态,每次跟服务器通讯完成后就会断开连接。 在没有websocket之前web系统如果要做双工通讯往往使用http long polling技术。http long polling 每次往服务器发送请求后,服务端不会立刻返回信息来结束请求,而是一直挂着直到有数据需要返回,或者等待超时了才会返回。客户端在结束上一次请求后立刻再发送一次请求,如此反复。http long polling虽然能实现web系统的双工通讯,但是有个很大的问题,就是基于http协议客户端每次发送请求都需要携带巨大的头部。在并发交互少量数据的时候非常不划算,对服务器资源的消耗也是巨大的。 websocket很好的改善了以上问题。它基于tcp重新设计了一套协议,同时又兼容http,默认跟http一样使用80/443端口。websocket链接建立本质上就是一次http请求,直接使用http协议的upgrade头来标识这是一次websocket请求,服务端回复101状态码表示“握手”成功。
李明成
2020/03/18
1.1K0
2万字长文肝了一个实时聊天室,只为让她学会websocket
看演示不过瘾,我也玩一下(http://socket.vjscoder.com/websocket-chatroom/index.html#/)
前端胖头鱼
2022/07/25
9900
2万字长文肝了一个实时聊天室,只为让她学会websocket
WebSocket 介绍以及配合 STOMP 的使用
由于近期需要使用 WebSocket 的部分功能,然而在工作过程中,发现自己对这部分知识点不是很了解,而且对于后台同学提出的 WebSocket 和 STOMP 的组合,不知如何下手。经过相关资料查证,分享与大家,如有纰漏,希望不吝指出。 本文行文为三个部分,分别讲述:Socket 是什么,WebSocket 是什么,STOMP 是什么,如何结合后两者投入使用。
零式的天空
2022/03/25
3.2K0
Websocket 简介
  随着网际网络的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的完善,WebSocket协议被提出,它实现了浏览器与服务器的全双工通讯,扩充套件了浏览器与服务端的通讯功能,使服务端也能主动向客户端传送资料。
老猫-Leo
2023/12/11
5350
Websocket 简介
WebSocket 基础与应用系列 —— 抓个 WebSocket 的包
在传统的 Web 中,要实现实时通信,通用的方式是采用 HTTP 协议不断发送请求,即轮询(Polling)。
程序员海军
2021/10/11
1.3K0
WebSocket 基础与应用系列 ——  抓个 WebSocket 的包
websocket
短轮询(Polling)的实现思路就是 浏览器端 每隔几秒钟向 服务器端 发送http请求,服务端在收到请求后,不论是否有数据更新,都直接进行响应。 在服务端响应完成,就会关闭这个Tcp连接 ,如下图所示:
用户10106350
2022/10/28
2.7K0
【WebSocket】505- WebSocket 入门到精通
WebSocket的出现,使得浏览器具备了实时双向通信的能力。本文由浅入深,介绍了WebSocket如何建立连接、交换数据的细节,以及数据帧的格式。此外,还简要介绍了针对WebSocket的安全攻击,以及协议是如何抵御类似攻击的。
pingan8787
2020/03/02
1.9K0
什么是WebSocket协议?
WebSocket的出现,使得浏览器具备了实时双向通信的能力。本文由浅入深,介绍了WebSocket如何建立连接、交换数据的细节,以及数据帧的格式。此外,还简要介绍了针对WebSocket的安全攻击,以及协议是如何抵御类似攻击的。
技术从心
2019/08/06
1.6K0
什么是WebSocket协议?
websocket深入浅出
答: 它是一种网络通信协议,是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
全栈程序员站长
2022/09/14
2.3K0
websocket深入浅出
解密与探究:理解WebSocket协议与报文格式
过去,在创建需要在客户端和服务端之间进行双向通信的 Web 应用程序(比如,即时通讯和游戏应用程序)时,需要滥用 HTTP,轮询服务端以获取更新,并且通过单独的 HTTP 调用发送上行通知。
小阑本阑
2023/08/24
2.4K0
解密与探究:理解WebSocket协议与报文格式
WebSocket攻防对抗一篇通
在一次做项目的时候本来是想去点击Burpsuite的Proxy界面的HTTP History选项卡来查看HTTP历史请求记录信息并做测试的,但是在查看的时候却下意识的点击到了HTTP Proxy右侧的"WebSockets History"选项卡中,从界面的交互历史中发现网站有使用WebSocket进行通信,虽然之前有对Websocket有一些简单的了解(比如:跨越问题),但是未对此进行深入研究,这让我产生了需要深入研究一下的想法
Al1ex
2024/06/21
4550
WebSocket攻防对抗一篇通
WebSocket
HTTP协议是一种无状态协议,服务器端本身不具有识别客户端的能力,必须借助外部机制,比如session和cookie,才能与特定客户端保持对话。
奋飛
2019/08/15
1.9K0
消息推送技术,除了websocket还知道那些?
WebSocket是一种网络通信协议,它提供了在单个TCP连接上进行全双工通信的能力。这意味着数据可以在客户端和服务器之间双向流动,而无需客户端通过轮询或重复请求来获取更新。
老K博客
2024/06/01
8150
消息推送技术,除了websocket还知道那些?
WebSocket的JavaScript例子
在HTML5规范中,我最喜欢的Web技术就是正迅速变得流行的WebSocket API。WebSocket提供了一个受欢迎的技术,以替代我们过去几年一直在用的Ajax技术。这个新的API提供了一个方法,从客户端使用简单的语法有效地推动消息到服务器。让我们看一看HTML5的WebSocket API:它可用于客户端、服务器端。而且有一个优秀的第三方API,名为Socket.IO。
周陆军博客
2023/05/07
5140
WebSocket 教程 转
初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?
wuweixiang
2018/08/14
5280
WebSocket 教程
                                                                            转
【.NET】简单实现Websocket客户端和服务端通讯方式(原生开发方式和DotNetty方式)
前言:早上在一个群里看到一个小伙子的ID叫netty,就想到了dotnetty,于是就顺便想起写个dotnetty的入门文章好了。由于dotnetty不维护了,所以后面也提供了一个原生的开发方式(.NET CORE 3.1以及以上版本支持)
Wesky
2024/08/13
5190
【.NET】简单实现Websocket客户端和服务端通讯方式(原生开发方式和DotNetty方式)
相关推荐
webSocket和EventSource的区别
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验