多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
## 什么是 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(); ```