## 什么是 Socket.IO
Socket.IO 是一个库,可以在客户端和服务器之间实现**低延迟**,**双向**和**基于事件的**通信。
![](https://img.kancloud.cn/c9/49/c9497048429c80c59ba368cf90b549f3_840x131.png)
## 版本差异
Socket.IO自诞生以来经历了多个版本的迭代,主要版本有1.x、2.x和3.x。每个版本都带来了新特性和性能改进。
* **1.x版本**:这是Socket.IO的初始版本,奠定了基础架构。提供了基本的实时通信功能。
* **2.x版本**:引入了许多新特性,比如更好的错误处理机制、改进的协议、更加稳定的连接管理等。
* **3.x版本**:带来了更高的性能和更低的延迟。它还增强了对TypeScript的支持,并优化了与其他框架的集成。
* **4.x版本**:基于WebSocket的通信协议已更新,以支持HTTP/2。客户端和服务器之间的通信协议有所简化。服务器和客户端都已更新以使用更现代的JavaScript。服务器API有重大更改,以提高灵活性和简化配置。移除了对Node.js的旧版本支持。
## 语言实现
### 服务器实现
|语言 | 网站 |
|----------|---------------|
| JavaScript (Node.js) | - [Installation steps](../02-Server/server-installation.md)<br/>- [API](../../server-api.md)<br/>- [Source code](https://github.com/socketio/socket.io) |
| JavaScript (Deno) | https://github.com/socketio/socket.io-deno |
| Java | https://github.com/mrniko/netty-socketio |
| Java | https://github.com/trinopoty/socket.io-server-java |
| Python | https://github.com/miguelgrinberg/python-socketio |
| Golang | https://github.com/googollee/go-socket.io |
| Rust | https://github.com/Totodore/socketioxide
| PHP | https://github.com/walkor/phpsocket.io |
### 客户端实现
| 语言| 网站 |
|------------------|-----------------|
| JavaScript (browser, Node.js or React Native) | - [Installation steps](../03-Client/client-installation.md)<br/>- [API](../../client-api.md)<br/>- [Source code](https://github.com/socketio/socket.io-client) |
| JavaScript (for WeChat Mini-Programs) | https://github.com/weapp-socketio/weapp.socket.io |
| Java | https://github.com/socketio/socket.io-client-java |
| C++ | https://github.com/socketio/socket.io-client-cpp |
| Swift | https://github.com/socketio/socket.io-client-swift |
| Dart | https://github.com/rikulo/socket.io-client-dart |
| Python | https://github.com/miguelgrinberg/python-socketio |
| .Net | https://github.com/doghappy/socket.io-client-csharp |
| Rust | https://github.com/1c3t3a/rust-socketio |
| Kotlin | https://github.com/icerockdev/moko-socket-io |
| PHP | https://github.com/ElephantIO/elephant.io |
## Socket.IO 不是什么
> Socket.IO 不是 WebSocket 实现。
尽管 Socket.IO 确实在可能的情况下使用 WebSocket 进行传输,但它会向每个数据包添加额外的元数据。这就是为什么 WebSocket 客户端将无法成功连接到 Socket.IO 服务器,并且 Socket.IO 客户端也将无法连接到普通 WebSocket 服务器。
```
// WARNING: the client will NOT be able to connect!
const socket = io("ws://echo.websocket.org");
```
> Socket.IO 不适合在移动应用的后台服务中使用。
Socket.IO 库与服务器保持开放的 TCP 连接,这可能会导致用户消耗大量电池。对于此用例,请使用专用消息传递平台(例如[FCM](https://firebase.google.com/docs/cloud-messaging))。
## 特性
以下是 Socket.IO 通过普通 WebSocket 提供的功能:
### HTTP 长轮询回退
如果无法建立 WebSocket 连接,连接将回退到 HTTP 长轮询。
此功能是十多年前创建 Socket.IO 项目时人们使用 Socket.IO 的第一大原因(!),因为浏览器对 WebSockets 的支持仍处于起步阶段。
即使大多数浏览器现在都支持 WebSocket(超过[97%](https://caniuse.com/mdn-api_websocket)),它仍然是一个很棒的功能,因为我们仍然收到用户的报告,称他们无法建立 WebSocket 连接,因为他们位于某些配置错误的代理后面。
### 自动重连
在某些特定条件下,服务器和客户端之间的 WebSocket 连接可能会中断,而双方都不知道链接的中断状态。
这就是 Socket.IO 包含心跳机制的原因,该机制会定期检查连接的状态。
当客户端最终断开连接时,它会自动以指数回退延迟重新连接,以免服务器不堪重负。
### 数据包缓冲
当客户端断开连接时,数据包会自动缓存,并在重新连接时发送。
更多信息在[此处](https://socket.nodejs.cn/docs/v4/client-offline-behavior/#buffered-events)。
### 回执
Socket.IO 提供了一种发送事件和接收响应的便捷方法:
发送者
~~~
socket.emit("hello", "world", (response) => { console.log(response); // "got it"});
~~~
接收者
~~~
socket.on("hello", (arg, callback) => { console.log(arg); // "world" callback("got it");});
~~~
你还可以添加超时:
~~~
socket.timeout(5000).emit("hello", "world", (err, response) => { if (err) { // the other side did not acknowledge the event in the given delay } else { console.log(response); // "got it" }});
~~~
### 广播
在服务器端,你可以向[所有连接的客户端](https://socket.nodejs.cn/docs/v4/broadcasting-events/)或[给一部分客户端](https://socket.nodejs.cn/docs/v4/rooms/)发送事件:
~~~
// to all connected clientsio.emit("hello");// to all connected clients in the "news" roomio.to("news").emit("hello");
~~~
这在[扩展到多个节点](https://socket.nodejs.cn/docs/v4/using-multiple-nodes/)时也有效。
### 多路复用
命名空间允许你通过单个共享连接拆分应用的逻辑。例如,如果你想要创建只有授权用户才能加入的 "管理" 通道,这可能会很有用。
~~~
io.on("connection", (socket) => { // classic users});io.of("/admin").on("connection", (socket) => { // admin users});
~~~
## 实战示例
### 服务器端
服务器端这里使用`PHPSocket.IO`。PHPSocket.IO是基于Workerman开发的PHP版本的`socket.IO`服务。可用于服务器消息的推送、聊天室、客服系统的开发。
官方文档:`https://github.com/walkor/phpsocket.io`
#### 安装
```php
composer require workerman/phpsocket.io
```
#### 服务端`server.php`
```php
<?php
/**
* @desc server.php 描述信息
* @author Tinywan(ShaoBo Wan)
*/
declare(strict_types=1);
require_once '../vendor/autoload.php';
use Workerman\Worker;
use PHPSocketIO\SocketIO;
// 创建socket.io服务端,监听3120端口
$io = new SocketIO(2024);
// 当有客户端连接时打印一行文字
$io->on('connection', function($socket)use($io){
echo '[x] new connection coming'.PHP_EOL;
});
Worker::runAll();
```
启动服务端
```
php server.php start
```
![](https://img.kancloud.cn/a8/78/a8785110f4f56a871f6fa84f35ce0d81_999x209.png)
### 客户端
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>phpsocket.io 客户端</title>
</head>
<body>
<script src='https://cdn.bootcss.com/socket.io/2.0.3/socket.io.js'></script>
<script>
var socket = io('http://127.0.0.1:2024');
socket.on('connect', function(){
console.log('connect success');
});
</script>
</body>
</html>
```
浏览器打开后,服务端输出
```
---------------------------------------------- WORKERMAN -----------------------------------------------
Workerman version:4.1.15 PHP version:7.4.28
----------------------------------------------- WORKERS ------------------------------------------------
worker listen processes status
PHPSocketIO socketIO://0.0.0.0:2024 1 [ok]
[x] new connection coming
[x] new connection coming
[x] new connection coming
```
## 自定义事件
socket.io主要是通过事件来进行通讯交互的。socket连接除了自带的`connect`,`message`,`disconnect`三个事件以外,在服务端和客户端开发者可以自定义其它事件。
服务端和客户端都通过emit方法触发对端的事件。例如下面的代码在服务端定义了一个`chat message`事件,事件参数为`$msg`。
```php
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use PHPSocketIO\SocketIO;
$io = new SocketIO(2024);
// 当有客户端连接时
$io->on('connection', function($socket)use($io){
// 定义chat message事件回调函数
$socket->on('chat message', function($msg)use($io){
// 触发所有客户端定义的chat message from server事件
$io->emit('chat message from server', $msg);
});
});
Worker::runAll();
```
客户端通过下面的方法触发服务端的`chat message`事件。
```
<script src='//cdn.bootcss.com/socket.io/1.3.7/socket.io.js'></script>
<script>
// 连接服务端
var socket = io('http://127.0.0.1:2024');
// 触发服务端的chat message事件
socket.emit('chat message', '这个是消息内容...');
// 服务端通过emit('chat message from server', $msg)触发客户端的chat message from server事件
socket.on('chat message from server', function(msg){
console.log('get message:' + msg + ' from server');
});
</script>
```
## workerStart事件
`phpsocket.io`提供了`workerStart`事件回调,也就是当进程启动后准备好接受客户端链接时触发的回调。 一个进程生命周期只会触发一次。可以在这里设置一些全局的事情,比如开一个新的Worker端口等等。
```
require_once __DIR__ . '/vendor/autoload.php';
use Workerman\Worker;
use PHPSocketIO\SocketIO;
$io = new SocketIO(9120);
// 监听一个http端口,通过http协议访问这个端口可以向所有客户端推送数据(url类似http://ip:9191?msg=xxxx)
$io->on('workerStart', function()use($io) {
$inner_http_worker = new Worker('http://0.0.0.0:9191');
$inner_http_worker->onMessage = function($http_connection, $data)use($io){
if(!isset($_GET['msg'])) {
return $http_connection->send('fail, $_GET["msg"] not found');
}
$io->emit('chat message', $_GET['msg']);
$http_connection->send('ok');
};
$inner_http_worker->listen();
});
// 当有客户端连接时
$io->on('connection', function($socket)use($io){
// 定义chat message事件回调函数
$socket->on('chat message', function($msg)use($io){
// 触发所有客户端定义的chat message from server事件
$io->emit('chat message from server', $msg);
});
});
Worker::runAll();
```
- 设计模式系列
- 工厂方法模式
- 序言
- Windows程序注册为服务的工具WinSW
- 基础
- 安装
- 开发规范
- 目录结构
- 配置
- 快速入门
- 架构
- 请求流程
- 架构总览
- URL访问
- 容器和依赖注入
- 中间件
- 事件
- 代码层结构
- 四个层次
- 路由
- 控制器
- 请求
- 响应
- 数据库
- MySQL实时同步数据到ES解决方案
- 阿里云DTS数据MySQL同步至Elasticsearch实战
- PHP中的MySQL连接池
- PHP异步非阻塞MySQL客户端连接池
- 模型
- 视图
- 注解
- @SpringBootApplication(exclude={DataSourceAutoConfiguration.calss})
- @EnableFeignClients(basePackages = "com.wotu.feign")
- @EnableAspectJAutoProxy
- @EnableDiscoveryClient
- 错误和日志
- 异常处理
- 日志处理
- 调试
- 验证
- 验证器
- 验证规则
- 扩展库
- 附录
- Spring框架知识体系详解
- Maven
- Maven和Composer
- 构建Maven项目
- 实操课程
- 01.初识SpringBoot
- 第1章 Java Web发展史与学习Java的方法
- 第2章 环境与常见问题踩坑
- 第3章 springboot的路由与控制器
- 02.Java编程思想深度理论知识
- 第1章 Java编程思想总体
- 第2章 英雄联盟的小案例理解Java中最为抽象的概念
- 第3章 彻底理解IOC、DI与DIP
- 03.Spring与SpringBoot理论篇
- 第1章 Spring与SpringBoot导学
- 第2章 Spring IOC的核心机制:实例化与注入
- 第3章 SpringBoot基本配置原理
- 04.SprinBoot的条件注解与配置
- 第1章 conditonal 条件注解
- 第2章 SpringBoot自动装配解析
- 05.Java异常深度剖析
- 第1章 Java异常分类剖析与自定义异常
- 第2章 自动配置Url前缀
- 06.参数校验机制与LomBok工具集的使用
- 第1章 LomBok工具集的使用
- 第2章 参数校验机制以及自定义校验
- 07.项目分层设计与JPA技术
- 第1章 项目分层原则与层与层的松耦合原则
- 第2章 数据库设计、实体关系与查询方案探讨
- 第3章 JPA的关联关系与规则查询
- 08.ORM的概念与思维
- 第1章 ORM的概念与思维
- 第2章 Banner等相关业务
- 第3章 再谈数据库设计技巧与VO层对象的技巧
- 09.JPA的多种查询规则
- 第1章 DozerBeanMapper的使用
- 第2章 详解SKU的规格设计
- 第3章 通用泛型Converter
- 10.令牌与权限
- 第1章 通用泛型类与java泛型的思考
- 常见问题
- 微服务
- demo
- PHP中Self、Static和parent的区别
- Swoole-Cli
- 为什么要使用现代化PHP框架?
- 公众号
- 一键部署微信公众号Markdown编辑器(支持适配和主题设计)
- Autodesigner 2.0发布
- Luya 一个现代化PHP开发框架
- PHPZip - 创建、读取和管理 ZIP 文件的简单库
- 吊打Golang的PHP界天花板webman压测对比
- 简洁而强大的 YAML 解析库
- 推荐一个革命性的PHP测试框架:Kahlan
- ServBay下一代Web开发环境
- 基于Websocket和Canvas实现多人协作实时共享白板
- Apipost预执行脚本如何调用外部PHP语言
- 认证和授权的安全令牌 Bearer Token
- Laradock PHP 的 Docker 完整本地开发环境
- 高效接口防抖策略,确保数据安全,避免重复提交的终极解决方案!
- TIOBE 6月榜单:PHP稳步前行,编程语言生态的微妙变化
- Aho-Corasick字符串匹配算法的实现
- Redis键空间通知 Keyspace Notification 事件订阅
- ServBay如何启用并运行Webman项目
- 使用mpdf实现导出pdf文件功能
- Medoo 轻量级PHP数据库框架
- 在PHP中编写和运行单元测试
- 9 PHP运行时基准性能测试
- QR码生成器在PHP中的源代码
- 使用Gogs极易搭建的自助Git服务
- Gitea
- webman如何记录SQL到日志?
- Sentry PHP: 实时监测并处理PHP应用程序中的错误
- Swoole v6 Alpha 版本已发布
- Proxypin
- Rust实现的Redis内存数据库发布
- PHP 8.4.0 Alpha 1 测试版本发布
- 121
- Golang + Vue 开发的开源轻量 Linux 服务器运维管理面板
- 内网穿透 FRP VS Tailscale
- 新一代开源代码托管平台Gitea
- 微服务系列
- Nacos云原生配置中心介绍与使用
- 轻量级的开源高性能事件库libevent
- 国密算法
- 国密算法(商用密码)
- GmSSL 支持国密SM2/SM3/SM4/SM9/SSL 密码工具箱
- GmSSL PHP 使用
- 数据库
- SQLite数据库的Web管理工具
- 阿里巴巴MySQL数据库强制规范
- PHP
- PHP安全测试秘密武器 PHPGGC
- 使用declare(strict_types=1)来获得更健壮的PHP代码
- PHP中的魔术常量
- OSS 直传阿里腾讯示例
- PHP源码编译安装APCu扩展实现数据缓存
- BI性能DuckDB数据管理系统
- 为什么别人可以是架构师!而我却不是?
- 密码还在用 MD5 加盐?不如试试 password_hash
- Elasticsearch 在电商领域的应用与实践
- Cron 定时任务入门
- 如何动态设置定时任务!而不是写死在Linux Crontab
- Elasticsearch的四种查询方式,你知道多少?
- Meilisearch vs Elasticsearch
- OpenSearch vs Elasticsearch
- Emlog 轻量级开源博客及建站系统
- 现代化PHP原生协程引擎 PRipple
- 使用Zephir编写C扩展将PHP源代码编译加密
- 如何将PHP源代码编译加密,同时保证代码能正常的运行
- 为什么选择Zephir给PHP编写动态扩展库?
- 使用 PHP + XlsWriter实现百万级数据导入导出
- Rust编写PHP扩展
- 阿里云盘开放平台对接进行文件同步
- 如何构建自己的PHP静态可执行文件
- IM后端架构
- RESTful设计方法和规范
- PHP编译器BPC 7.3 发布,成功编译ThinkPHP8
- 高性能的配置管理扩展 Yaconf
- PHP实现雪花算法库 Snowflake
- PHP官方现代化核心加密库Sodium
- pie
- 现代化、精简、非阻塞PHP标准库PSL
- PHP泛型和集合
- 手把手教你正确使用 Composer包管理
- JWT双令牌认证实现无感Token自动续期
- 最先进PHP大模型深度学习库TransformersPHP
- PHP如何启用 FFI 扩展
- PHP超集语言PXP
- 低延迟双向实时事件通信 Socket.IO
- PHP OOP中的继承和多态
- 强大的现代PHP高级调试工具Kint
- PHP基金会
- 基于webman+vue3高质量中后台框架SaiAdmin
- 开源免费的定时任务管理系统:Gocron
- 简单强大OCR工具EasyOCR在PHP中使用
- PHP代码抽象语法树工具PHP AST Viewer
- MySQL数据库管理工具PHPMyAdmin
- Rust编写的一款高性能多人代码编辑器Zed
- 超高性能PHP框架Workerman v5.0.0-beta.8 发布
- 高并发系列
- 入门介绍及安装
- Lua脚本开发 Hello World
- 执行流程与阶段详解
- Nginx Lua API 接口开发
- Lua模块开发
- OpenResty 高性能的正式原因
- 记一次查找 lua-resty-mysql 库 insert_id 的 bug
- 包管理工具OPM和LuaRocks使用
- 异步非阻塞HTTP客户端库 lua-resty-http
- Nginx 内置绑定变量
- Redis协程网络库 lua-resty-redis
- 动态HTML渲染库 lua-testy-template
- 单独的
- StackBlitz在线开发环境
- AI
- 基础概念
- 12312
- 基础镜像的坑
- 利用phpy实现 PHP 编写 Vision Transformer (ViT) 模型
- 语义化版本 2.0.0