前言
在移动应用开发中,我们通常扮演'客户端'的角色,去连接远程的 WebSocket 服务。但有时,我们需要在设备本身运行一个微型服务器,例如用于局域网内的设备发现、P2P 文件传输信令,或者在调试模式下作为数据广播源。
shelf_web_socket 是基于 Dart 标准 Web 服务器框架 shelf 的 WebSocket 处理器。它能让你在 Flutter 应用(包括 OpenHarmony)中轻松启动一个能够处理 WebSocket 连接的 HTTP 服务。
一、核心概念
- Shelf: Dart 的 Web 服务器中间件管道框架(类似 Express.js)。
- Handler: 处理请求并返回响应的函数。
- WebSocketChannel: 下层封装,让 WebSocket 操作像 Stream 一样简单。
通信流程:
- 建立连接 ws://ip:port
- 协议升级请求 (Upgrade Request)
- 升级成功 (Success)
- 数据流/接收端 (Stream/Sink)
- WebSocket 客户端 (App/浏览器) <-> 鸿蒙应用 (shelf_web_socket) <-> 处理器 (shelf handler) <-> 通信通道 (WebSocketChannel)
二、集成与基础用法
2.1 添加依赖
dependencies:
shelf: ^1.4.0
shelf_web_socket: ^3.0.0
web_socket_channel: ^3.0.0
2.2 启动基础服务
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
void main() async {
// 定义 WebSocket 处理器
var handler = webSocketHandler((WebSocketChannel webSocket) {
webSocket.stream.listen((message) {
print('收到消息:$message');
webSocket.sink.add('服务端已收到:$message');
});
});
// 启动服务,监听所有 IP (0.0.0.0)
var server = await shelf_io.serve(handler, '0.0.0.0', 8080);
print('WebSocket 服务已启动:ws://${server.address.host}:${server.port}');
}
三、进阶场景与示例
3.1 示例一:广播消息
实现一个聊天室功能,将一个客户端发来的消息广播给所有连接者。
import 'package:shelf_web_socket/shelf_web_socket.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
final List<WebSocketChannel> _clients = [];
var broadcastHandler = webSocketHandler((WebSocketChannel webSocket) {
_clients.add(webSocket);
print('新客户端连接,当前在线:${_clients.length}');
webSocket.stream.listen((message) {
// 广播给其他客户端
for (var client in _clients) {
if (client != webSocket) {
client.sink.add(message);
}
}
}, onDone: () {
_clients.remove(webSocket);
print('客户端断开,剩余:${_clients.length}');
});
});
3.2 示例二:鉴权校验
在建立连接前检查 Header 中的 Token。
import 'package:shelf/shelf.dart';
import 'package:shelf_web_socket/shelf_web_socket.dart';
Handler authMiddleware(Handler innerHandler) {
return (Request request) {
if (request.headers['Authorization'] != 'Bearer my_secret_token') {
return Response.forbidden('未授权访问');
}
return innerHandler(request);
};
}
// 使用 Pipeline 组装
// var handler = Pipeline().addMiddleware(authMiddleware).addHandler(wsHandler);


