Dart RawServerSocket
最后修改于 2025 年 4 月 4 日
Dart 中的 RawServerSocket
类提供了低级的 TCP 服务器套接字功能。它是 Dart 的 dart:io
库的一部分,用于非 Web 应用程序。
RawServerSocket 允许与 TCP 客户端进行直接的字节级通信。它适用于自定义协议、性能关键型应用程序和二进制数据。
基本定义
RawServerSocket
是一个服务器端套接字,用于监听传入的 TCP 连接。它提供原始字节流,不进行更高级别的协议处理。
主要功能包括异步操作、连接事件处理以及对套接字流的直接访问。它是构建自定义网络服务器的基础。
基本回显服务器
此示例展示了一个使用 RawServerSocket 的简单回显服务器。
import 'dart:io'; void main() async { var server = await RawServerSocket.bind('127.0.0.1', 4040); print('Echo server listening on ${server.address}:${server.port}'); server.listen((client) { client.listen((data) { client.add(data); // Echo back received data }, onDone: () => client.close()); }); }
我们创建一个在 localhost 端口 4040 上监听的服务器。当客户端连接时,我们会将它们发送的任何数据回显回去。服务器异步处理多个客户端。
$ dart main.dart Echo server listening on 127.0.0.1:4040
处理客户端连接
此示例演示了详细的客户端连接处理。
import 'dart:io'; void main() async { var server = await RawServerSocket.bind('0.0.0.0', 4041); print('Server started on port ${server.port}'); server.listen((client) { print('Client connected from ${client.remoteAddress.address}'); client.handleError((error) { print('Client error: $error'); }, test: (error) => true); client.listen((data) { print('Received ${data.length} bytes'); client.add([0x01, 0x02, 0x03]); // Send response }, onDone: () { print('Client disconnected'); client.close(); }); }); }
我们记录客户端连接,处理错误,并发送固定响应。remoteAddress 属性用于标识连接的客户端。错误处理可确保服务器的稳定性。
$ dart main.dart Server started on port 4041 Client connected from 127.0.0.1 Received 5 bytes Client disconnected
广播服务器
此示例展示了一个将消息广播到所有连接客户端的服务器。
import 'dart:io'; import 'dart:async'; void main() async { var server = await RawServerSocket.bind('127.0.0.1', 4042); var clients = <RawSocket>[]; server.listen((client) { clients.add(client); print('New client (${clients.length} total)'); client.listen((_) {}, onDone: () { clients.remove(client); print('Client disconnected (${clients.length} remaining)'); }); }); // Broadcast timer Timer.periodic(Duration(seconds: 2), (_) { var message = 'Server time: ${DateTime.now()}\n'.codeUnits; for (var client in clients) { client.add(message); } }); }
我们维护一个已连接客户端列表,并每 2 秒广播一次时间更新。服务器跟踪客户端的连接和断开连接。
$ dart main.dart New client (1 total) New client (2 total) Client disconnected (1 remaining)
端口扫描器
此示例演示了如何使用 RawServerSocket 检查端口可用性。
import 'dart:io'; Future<bool> isPortAvailable(int port) async { try { var server = await RawServerSocket.bind('127.0.0.1', port); await server.close(); return true; } catch (e) { return false; } } void main() async { var ports = [80, 4040, 8080, 3000]; for (var port in ports) { var available = await isPortAvailable(port); print('Port $port: ${available ? 'available' : 'in use'}'); } }
我们尝试绑定到每个端口以检查可用性。成功绑定意味着该端口可用。服务器在检查后立即关闭。
$ dart main.dart Port 80: in use Port 4040: available Port 8080: in use Port 3000: available
自定义协议服务器
此示例实现了一个简单的自定义二进制协议服务器。
import 'dart:io'; void main() async { var server = await RawServerSocket.bind('127.0.0.1', 4043); print('Custom protocol server started'); server.listen((client) { var buffer = <int>[]; client.listen((data) { buffer.addAll(data); // Process complete messages (delimited by 0xFF) while (buffer.contains(0xFF)) { var messageEnd = buffer.indexOf(0xFF); var message = buffer.sublist(0, messageEnd); buffer.removeRange(0, messageEnd + 1); print('Received message: $message'); client.add([...message.reversed, 0xFF]); // Send reversed } }, onDone: () => client.close()); }); }
我们实现了一个简单的协议,其中消息以 0xFF 结尾。服务器处理完整的消息并以反转的数据响应。部分消息会被缓冲。
$ dart main.dart Custom protocol server started Received message: [72, 101, 108, 108, 111]
最佳实践
- 错误处理:始终为套接字实现错误处理程序
- 资源清理:完成后关闭套接字以释放资源
- 缓冲:通过适当的缓冲处理部分数据
- 背压:监控套接字写入缓冲区以避免过载
- 安全性:验证所有传入数据并限制连接
来源
本教程通过实际示例介绍了 Dart 的 RawServerSocket 类,展示了服务器创建、客户端处理和自定义协议实现。
作者
列出 所有 Dart 教程。