惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Exploit Database - CXSecurity.com
F
Fortinet All Blogs
U
Unit 42
F
Full Disclosure
雷峰网
雷峰网
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tailwind CSS Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
罗磊的独立博客
D
DataBreaches.Net
C
Check Point Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
O
OpenAI News
C
CXSECURITY Database RSS Feed - CXSecurity.com
aimingoo的专栏
aimingoo的专栏
S
Security @ Cisco Blogs
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Hacker News
The Hacker News
Webroot Blog
Webroot Blog
Security Latest
Security Latest
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Google DeepMind News
Google DeepMind News
酷 壳 – CoolShell
酷 壳 – CoolShell
N
News | PayPal Newsroom
P
Proofpoint News Feed
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
C
Cybersecurity and Infrastructure Security Agency CISA
N
News and Events Feed by Topic
Google Online Security Blog
Google Online Security Blog
H
Help Net Security
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog
M
MIT News - Artificial intelligence
Vercel News
Vercel News
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
IT之家
IT之家
MyScale Blog
MyScale Blog
腾讯CDC

碎言

不懂就别瞎掰掰:【程序员的常识】写的什么玩意? AI 辅助编程下的程序设计与代码编写 使用 Next.js 和 Tailwind CSS 构建可编辑和删除的 ToDo 待办事项应用 探索编程新境界:MarsCode 助你一臂之力 使用 Next.js 和 Tailwind CSS 搭建静态图片展示站点并部署到 Vercel AI 辅助编程:免费工具的优缺点及官网一览 GitHub push更新总是失败,写个python脚本解决 把博客从GitHub迁移到到了vercel ComfyUI 和 Flux.1 安装与使用教程 Flux.1 入门必知:硬件、环境、模型 Git项目的子文件夹中的内容无法同步到远程仓库的解决方法 blender流体Fluid使用中没有流体、流体穿模等一些问题的解决方法 博客聚合网站:积薪,竟然关闭了! blender日常使用中的一些技巧 虽然只有我自己在用,但还是更新了碎言博客的源代码, 与其在迷茫中困惑,不如在努力中前进 差点忘了我还有一个博客... 秧歌、博客和AI 终于熬到了新手上路 好久没有更新博客了。。。 老妈大腿骨骨折,最近一直在医院护理 Hello, September! Ubuntu开机自动启动Docker容器运行WordPress Docker 简单快速安装部署WordPress Docker下安装MySQL 加碘盐能防核辐射的话,还怕什么核战争? shields.io 一个简洁、一致、清晰的徽章 Ubuntu下使用root登录ssh的设置 GitHub Actions 构建、部署 Next.js项目 我又用回了"IE"--edge ubuntu-22-live-server 设置固定IP Next项目部署GitHub pages的一些坑 整理了一个下午的收藏夹...... 短暂而忙碌的暑假即将谢幕 GitHub Actions 是干什么用的? 放弃Next.js重构博客:经验、教训与未来技术探索 关于Google LCP 问题:超过了2.5秒 验证已通过 仅用了几个小时就使用next.js重构博客的所有功能 关于使用Next.js重构博客构思的记录 使用Tailwind css和JavaScript实现一个简单的返回顶部功能 罗技K380 F1-F12 功能键锁定 PHILIPS猛禽SPK8404机械键盘手感真是超赞! 局域网的DNS设置192.168.0.1与8.8.8.8,114.114.114.114有什么区别? 史诗结合的浪漫:《长安三万里》 聊 聊 友 情 链 接 1767个中文博客的数据洞察:中文博主都喜欢干啥? python requests 设置读取超时时间 八月回顾:博客之路,一路前行 Docker基础学习笔记和常用命令汇总 vim常用命令整理 Ubuntu 22 安装Docker过程记录 使用python结合feedparser模块编写自己的私人RSS订阅程序 博客大数据分析:38880条博文揭示博主最爱写什么? Windows下国产杀毒软件还有选择吗?火绒安全可以一试。 export exports module.exports 这三个命令的区别是什么如何使用? 时代的变迁:从56K拨号上网到1G光纤的回忆 理工计算机专业准大学生如何选配笔记本? 使用JavaScript编写自己的私人RSS订阅程序 如何使用CSS为博客标题设置彩虹颜色? 最终还是决定使用传统的网线来解决千兆速率问题。 1300M USB双频2.4+5G无线网卡的一些常识和使用技巧 Python Gui新框架:NiceGui之初体验 pycharm 正在关闭项目(closing project)无法关闭退出程序的解决方法! 速度与优雅:博客性能优化之旅 久了,博客主题就会一直做减法 七月的焦虑 在react中使用复制插件clipboard.js react中如把HTML代码转成字符串进行渲染? react useEffect()中使用lodash库中的防抖debounce react useEffect() 为什么在开发模式的时候会执行两次? 七年之痒!别了我曾深爱的MacBookPro 前端React+Material UI开发环境的快速搭建 一键更新Github部署的静态博客 编程新手学习过程中如何更好的提问? Typed.js 一款有意思的网页打字机效果库 解决错误 ERROR [WinError 10049] 在其上下文中,该请求的地址无效。 Stable Diffusion 相关教程与模型的记录 Stable Diffusion ControlNet openpose 报错无法使用 在react或vue中使用localStorage存储数据 使用React+Vite+TailwindCSS+daisyUI打造一个简单的ToDos 碎言静态博客 聊聊Python中的装饰器 npm更换源与nrm安装与配置 pip临时修改下载源 Vue快速学习笔记(9)Vuetify配置及简单使用 Vue快速学习笔记(8)webpack4.X配置Vue开发打包环境 Vue快速学习笔记(5)使用路由vue-router(1) Vue快速学习笔记(4)Vue组件中的数据传递 Vue快速学习笔记(3)Vue的组件 Vue快速学习笔记(2)Vue中的监听与计算属性 Vue快速学习笔记(1)Vue实例基础 基于Django构建的小学生英文单词背写检测考试系统。 如何在Python程序中使用配置文件.ini(ConfigParser) 写在我的博客PV10万时:聊聊编程与画画 python3函数学习笔记简单总结 PythonINI配置文件读写的简单方法 Python open()函数文件打开、读、写操作总结 Python os.path模块中一些常用方法的整理总结 Python 采集数据三步曲之[Requests + re.py模块进行数据采集] Python 采集数据三步曲之[Requests开源协议的HTTP 库]
Socket.IO:实时通信的强大工具
J.sky · 2024-11-14 · via 碎言

一、 Socket.IO 简介

Socket.IO 由 Guillermo Rauch 开发,旨在解决 WebSocket 在不同浏览器和网络环境中的兼容性问题。它提供了统一的 API,让开发者无需担心底层传输协议的差异,轻松实现实时双向通信。

其主要特点包括:

跨平台支持:支持 Node.js、Python、Java、.NET 等多种语言和平台。例如,在 Python 中可以通过安装python-socketio库来创建服务器,有多种创建方式,如使用多进程多线程模式的 WSGI 服务器对接、作为 Flask 或 Django 应用的一部分,或者使用协程的方式运行(推荐)。

自动回退机制:如果 WebSocket 不可用,Socket.IO 会自动回退到其他协议,如 XHR 轮询、JSONP 轮询等。这样确保了在各种网络环境下都能实现实时通信。

事件驱动:基于事件的编程模型,支持自定义事件。开发者可以根据具体需求定义和处理各种事件,实现灵活的交互逻辑。

命名空间:支持命名空间,可以在同一连接中区分不同的逻辑通道。比如,可以创建不同的命名空间来处理不同类型的实时通信需求,提高代码的可维护性和扩展性。

房间机制:支持房间(Rooms)功能,可以实现群组通信。服务器端可以通过socket.join(room)让客户端加入特定房间,客户端也可以通过发送特定事件加入房间,实现高效的群组通信。

连接管理:内置心跳机制和重连功能,保证连接的稳定性和可靠性。即使在网络不稳定的情况下,也能自动尝试重新连接,确保实时通信不中断。

总之,Socket.IO 是一个强大且灵活的库,非常适合需要实时通信的应用,如聊天室、实时协作工具和在线游戏等。

二、安装与创建

(一)服务器端安装

在服务器端安装 Socket.IO 非常简单,首先确保你已经安装了 Node.js。然后,在命令行中运行以下命令来安装 Socket.IO:

npm install socket.io

(二)客户端安装

在客户端,可以通过<script>标签加载 Socket.IO 库。例如:

<script src="/socket.io/socket.io.js"></script>

(三)创建服务器

在 Node.js 中,可以直接使用http模块创建服务器并引入 Socket.IO:

const http = require('http');
const server = http.createServer();
const io = require('socket.io')(server);
server.listen(3000, () => {
    console.log('Server listening on port 3000');
});

在 Express 框架中创建 Socket.IO 服务器:

const express = require('express');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
server.listen(80);
app.get('/', function (req, res) {
    res.sendfile(__dirname + '/index.html');
});
io.on('connection', function (socket) {
    socket.emit('news', { hello: 'world' });
    socket.on('my other event', function (data) {
        console.log(data);
    });
});

在 KOA 框架中创建 Socket.IO 服务器:

const koa = require('koa');
const static = require('koa-static');
const path = require('path');
const bodyParser = require('koa-bodyparser');
const indexRouter = require('./routers/indexRouter');
const { createServer } = require('http');
const app = new koa();
const httpServer = createServer(app.callback());
const socketServer = require('./service/socketService');
socketServer(httpServer);
app.use(bodyParser());
app.use(static(path.join(__dirname, 'public')));
app.use(indexRouter.routes());
httpServer.listen(3000, () => {
    console.log('server start');
});

(四)建立连接

服务器和客户端建立连接的过程如下:在服务器端,当有客户端连接时,会触发connection事件。例如在 Node.js 中:

io.on('connection', (socket) => {
    console.log('A client connected');
});

在客户端,通过创建Socket实例并连接到服务器。例如:

const socket = io('http://localhost:3000');
socket.on('connect', () => {
    console.log('Connected to server');
});

当连接建立成功后,可以在服务器和客户端之间进行事件的发送和接收。

三、Socket 对象方法

(一)发送和接收数据

Socket.IO 通过事件进行通信,socket.emit()方法用于发送事件,socket.on()方法用于监听事件。 例如,在服务器端可以使用以下方式发送事件:

io.on('connection', (socket) => {
    socket.emit('customEvent', { message: 'Hello from server!' });
});

在客户端,可以通过以下方式监听事件并接收数据:

const socket = io('http://localhost:3000');
socket.on('customEvent', (data) => {
    console.log(data.message); // Hello from server!
});

(二)断开连接

在客户端和服务器端都可以主动断开连接。 客户端断开连接:可以在特定情况下调用socket.disconnect()方法来断开与服务器的连接。例如,当用户退出应用时,可以触发断开连接操作。 // 假设在某个用户操作后触发断开连接 socket.disconnect();

服务器端断开连接:服务器可以在特定条件下调用socket.disconnect(true)强制断开与某个客户端的连接。 当连接断开时,会触发相应的事件。在客户端,会触发socket.on('disconnect')事件;在服务器端,会触发socket.on('disconnect', (reason) => {... })事件,其中reason参数表示断开连接的原因。

(三)其他常用方法

SocketIO 对象有许多常用方法,如emit、close、on、setTimeout、setInterval、setLoop等。 emit:用于发送事件,可以携带数据和回调函数。例如:

socket.emit('eventName', data, function (response) {
    // 处理回调函数的响应
});

close:用于关闭连接。例如:

socket.close();

on:用于监听事件,并用回调函数处理事件。例如:

socket.on('eventName', function (data) {
    // 处理事件的数据
});

setTimeout:等待指定的时间后执行函数。例如:

socket.setTimeout(function () {
    console.log('Time out!');
}, 5000);

setInterval:按照指定的时间间隔定期执行函数。例如:

socket.setInterval(function () {
    console.log('Interval triggered!');
}, 2000);

setLoop:循环执行函数直至连接关闭。例如:

socket.setLoop(function () {
    socket.emit('loopEvent', { data: 'Loop data' });
});

四、命名空间与房间

(一)命名空间

命名空间是一种通信通道,允许通过单个共享连接拆分应用程序的逻辑。本质上,它就是指定不同的终点或路径,这一特性可以减少所需资源数目(如 TCP 连接数),同时通过隔离通信信道达到隔离应用的多个部分。 在 Socket.IO 中,默认命名空间是 /,客户端默认连接到这个命名空间,服务端也默认监听这个命名空间。例如:

// the following two will emit to all the sockets connected to `/`
io.sockets.emit('hi', 'everyone');
io.emit('hi', 'everyone'); // short form

每个默认命名空间都会触发一个 connection 事件,并以 socket 作为参数传递到事件响应中。 如果要设置一个自定义命名空间,可以在服务端调用 of 函数。例如:

const nsp = io.of('/my-namespace');
nsp.on('connection', function(socket){
    console.log('someone connected');
});
nsp.emit('hi', 'everyone!');

在客户端,告知 socket.io 客户端连接到对应的自定义命名空间的方法如下:

const socket = io('/my-namespace');

(二)房间

房间是在每个命名空间内定义的专属通道,sockets 可以 join 和 leave 房间。 加入房间:通过调用 join 函数可以让 socket 订阅一个指定通道。例如:

io.on('connection', function(socket){
    socket.join('some room');
});

离开房间:调用 leave 可以像调用 join 一样离开房间,这两个方法都是异步的,接受 callback 作用参数。例如:

socket.on('leaveRoom', function (data, fn) {
    socket.leave(data.roomName);
    fn({'code': 0, 'msg': '已退出房间', 'roomName': data.roomName});
});

向房间广播消息:可以通过 to 或者 in(两者等同)在频道内广播或发送消息。例如:

io.to('some room').emit('some event');

在不加入或指定房间的情况下,socket.io 会默认分配一个 default room。同一房间下的 socket 可以广播消息,例如:

clientSocket.on('joinRoom', function (data, fn) {
    clientSocket.join(data.roomName);
    fn({'code': 0, 'msg': '加入房间成功', 'roomName': data.roomName});
});

clientSocket.on('sendMsg', function (data, fn) {
    clientSocket.broadcast.to(data.roomName).emit('receiveMsg', data);
    fn({'code': 0, 'msg': '消息发生成功'});
});

五、Socket.IO 原理

(一)基于 WebSocket 和降级策略

Socket.IO 底层使用 engine.io 封装了一层协议。在支持 WebSocket 的环境中,Socket.IO 会优先使用 WebSocket 进行通信,以实现高效的双向通信。但当浏览器不支持 WebSocket 时,Socket.IO 会自动采用降级策略,拥有多种轮询解决方案,确保在各种网络环境下都能实现实时通信。例如,它可以使用 XHR 轮询、JSONP 轮询等方式。这样的设计使得 Socket.IO 具有极高的兼容性,能够适应不同的浏览器和网络环境。

(二)建立连接过程

WebSocket 建立连接的过程复用了 HTTP 的握手通道。客户端发送 HTTP 请求,并在请求头中带上特定的参数,如Connection: Upgrade、Upgrade: websocket,服务端识别该请求头之后,进行协议升级,使用 WebSocket 协议进行数据通信。

请求头参数说明如下:

Request URL:请求服务端地址。

Request Method:请求方式,支持get、post、option等。

Status Code 101 Switching Protocols:当收到 101 请求状态码时,表明服务端理解并同意客户端请求,更改Upgrade header字段。服务端也必须在响应中,生成对应的Upgrade值。

Connection:设置upgrade header,通知服务端,该request类型需要进行升级为 websocket。

upgrade_mechanism:规范。

Host:服务端 hostname。

Origin:客户端 hostname:port。

Sec-WebSocket-Extensions:客户端向服务端发起请求扩展列表,供服务端选择并在响应中返回。

Sec-WebSocket-Key:秘钥的值是通过规范中定义的算法进行计算得出,虽然不安全,但是可以阻止一些误操作的 websocket 请求。

Sec-WebSocket-Accept:计算公式为获取客户端请求 header 的值Sec-WebSocket-Key,使用魔数’258EAFA5-E914-47DA-95CA-C5AB0DC85B11’,通过 SHA1 进行加密计算(sha1(Sec-WebSocket-Key + magic)),将值转换为 base64。

Sec-WebSocket-Protocol:指定有限使用的 WebSocket 协议,可以是一个协议列表。服务端在响应中返回列表中支持的第一个值。

Sec-WebSocket-Version:指定通信时使用的 WebSocket 协议版本。最新版本为 13,历史版本也有其他值。

Upgrade:通知服务端,指定升级协议类型为 websocket。

响应头方面,服务端响应了Upgrade,此时,连接已经和 HTTP 没什么关系了,协议升级后双方建立的就是 WebSocket 连接。整个过程中,通过这样的握手方式,实现了从 HTTP 协议到 WebSocket 协议的转换,为客户端和服务端的双向通信奠定了基础。

六、应用与展望

(一)应用场景

实时分析:将数据推送到客户端,客户端表现为实时计数器、图表或日志客户。例如在金融交易平台中,可以实时更新股票价格、交易量等数据,让用户能够及时了解市场动态。在工业监控系统中,传感器数据可以通过 Socket.IO 实时传输到客户端,实现对生产过程的实时监测和分析。

实时通讯:创建实时的、多用户聊天室,消息即时传递。无论是社交应用、在线客服系统还是内部通讯工具,Socket.IO 都能提供高效的实时通讯功能。例如在在线游戏中,玩家之间的交流可以通过 Socket.IO 实现实时同步,提升游戏体验。

二进制流传输:从 1.0 版本开始,Socket.IO 支持任何形式的二进制文件传输,例如图片、视频、音频等。这在多媒体应用中非常有用,比如视频会议系统可以通过 Socket.IO 实时传输视频流,实现高清、低延迟的视频通信。

文档合并:允许多个用户同时编辑一个文档,并能够看到每个用户做出的修改。类似于 Google Docs 的在线文档编辑工具可以利用 Socket.IO 实现实时同步,提高协作效率。

(二)未来发展潜力

技术融合:随着技术的不断发展,Socket.IO 有望与其他新兴技术融合,如人工智能、区块链等。例如,结合人工智能技术,可以实现智能实时客服系统,通过分析用户的问题自动提供准确的回答。与区块链技术结合,可以实现安全、透明的实时数据传输和验证。

性能优化:随着用户对实时通信的要求越来越高,Socket.IO 将不断进行性能优化。这包括提高数据传输速度、降低延迟、优化资源占用等方面。例如,通过改进底层的 engine.io 协议,进一步提高在不同网络环境下的通信效率。

跨平台扩展:目前 Socket.IO 已经支持多种语言和平台,但未来有望进一步扩展到更多的领域。例如,在物联网领域,Socket.IO 可以实现设备之间的实时通信,为智能家居、智能交通等应用提供支持。

丰富的插件生态:Socket.IO 的插件生态将不断丰富,为开发者提供更多的功能扩展。例如,开发出更多的安全插件,加强实时通信的安全性;开发出更多的数据分析插件,帮助开发者更好地理解和利用实时数据。

总之,Socket.IO 在实时通信领域具有广阔的应用前景和发展潜力。随着技术的不断进步,它将继续为开发者提供强大的实时通信解决方案,推动实时应用的发展。