James 7 miesięcy temu
rodzic
commit
43f294d1d9

+ 156 - 0
lib/network/httpClientWrap.dart

@@ -0,0 +1,156 @@
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+
+enum HttpClientStatus {
+  idle,
+  connecting,
+  connected,
+  disconnected,
+  error,
+}
+
+typedef HttpClientStatusHandler = void Function(HttpClientStatus status);
+
+class HttpClientWrap {
+  final Duration retryInterval;
+  final Map<String, String>? defaultHeaders;
+
+  HttpClient? _httpClient;
+  bool _disposed = false;
+
+  HttpClientStatus _status = HttpClientStatus.idle;
+  HttpClientStatus get status => _status;
+
+  final List<HttpClientStatusHandler> _statusHandlers = [];
+
+  HttpClientWrap({
+    this.retryInterval = const Duration(seconds: 5),
+    this.defaultHeaders,
+  });
+
+  /// 发送 GET 请求
+  Future<dynamic> get(String url, {Map<String, String>? headers, dynamic body}) async {
+    return _sendRequest(url, 'GET', headers: headers, body: body);
+  }
+
+  /// 发送 POST 请求
+  Future<dynamic> post(String url, {Map<String, String>? headers, dynamic body}) async {
+    return _sendRequest(url, 'POST', headers: headers, body: body);
+  }
+
+  /// 发送 PUT 请求
+  Future<dynamic> put(String url, {Map<String, String>? headers, dynamic body}) async {
+    return _sendRequest(url, 'PUT', headers: headers, body: body);
+  }
+
+  /// 发送 DELETE 请求
+  Future<dynamic> delete(String url, {Map<String, String>? headers}) async {
+    return _sendRequest(url, 'DELETE', headers: headers);
+  }
+
+  Future<dynamic> _sendRequest(
+      String url,
+      String method, {
+        Map<String, String>? headers,
+        dynamic body,
+      }) async {
+    if (_disposed) {
+      throw StateError('HTTP Client has been disposed');
+    }
+
+    _updateStatus(HttpClientStatus.connecting);
+    _httpClient ??= HttpClient();
+
+    try {
+
+      late final Uri uri;
+      if ((method == 'GET') && (body != null)) {
+        uri = Uri.parse(url).replace(
+          queryParameters: body,
+        );
+      } else {
+        uri = Uri.parse(url);
+      }
+
+      final request = await _httpClient!.openUrl(method, uri);
+
+      // 设置请求头
+      final mergedHeaders = {...?defaultHeaders, ...?headers};
+      mergedHeaders.forEach((key, value) {
+        request.headers.set(key, value);
+      });
+
+      // 添加请求体(如果是POST/PUT)
+      if (body != null && (method == 'POST' || method == 'PUT')) {
+        if (body is Map || body is List) {
+          request.write(jsonEncode(body));
+        } else {
+          request.write(body.toString());
+        }
+      }
+
+      final response = await request.close();
+      _updateStatus(HttpClientStatus.connected);
+
+      // 处理响应
+      final responseBody = await response.transform(utf8.decoder).join();
+      dynamic decodedResponse;
+
+      try {
+        decodedResponse = jsonDecode(responseBody);
+      } catch (e) {
+        decodedResponse = responseBody;
+      }
+
+      // Log.d('get response: $decodedResponse');
+
+      _updateStatus(HttpClientStatus.idle);
+      return decodedResponse; // 直接返回响应数据
+
+    } catch (e) {
+      _handleError(e);
+      _scheduleRetry();
+      rethrow; // 抛出异常以便调用方捕获
+    }
+  }
+
+  /// 添加状态监听器
+  void addStatusListener(HttpClientStatusHandler handler) {
+    _statusHandlers.add(handler);
+  }
+
+  /// 移除状态监听器
+  void removeStatusListener(HttpClientStatusHandler handler) {
+    _statusHandlers.remove(handler);
+  }
+
+  /// 释放资源
+  Future<void> dispose() async {
+    _disposed = true;
+    _httpClient?.close();
+    _httpClient = null;
+    _statusHandlers.clear();
+    _updateStatus(HttpClientStatus.disconnected);
+  }
+
+  void _handleError(dynamic error) {
+    _updateStatus(HttpClientStatus.error);
+  }
+
+  void _scheduleRetry() {
+    if (_disposed) return;
+
+    Timer(retryInterval, () {
+      _updateStatus(HttpClientStatus.idle);
+    });
+  }
+
+  void _updateStatus(HttpClientStatus status) {
+    _status = status;
+    for (final handler in _statusHandlers) {
+      handler(status);
+    }
+  }
+}

+ 124 - 0
lib/network/httpServerWrap.dart

@@ -0,0 +1,124 @@
+
+import 'dart:async';
+import 'dart:io';
+import 'dart:convert';
+// import '../util/logger.dart';
+
+
+enum HttpServerStatus {
+  starting,
+  started,
+  stopping,
+  stopped,
+}
+
+typedef HttpRequestHandler = Future<void> Function(HttpRequest request);
+typedef HttpServerStatusHandler = void Function(HttpServerStatus status);
+
+
+class HttpServerWrap {
+
+  HttpServer? _server;
+
+  HttpServerStatus _status = HttpServerStatus.stopped;
+  HttpServerStatus get status => _status;
+
+  String? _serverAddress;
+  String? get serverAddress => _serverAddress;
+
+  // 用于向 UI 推送事件
+  final StreamController<String> _eventController = StreamController.broadcast();
+  Stream<String> get events => _eventController.stream;
+
+  // // 保存所有活跃的客户端连接(可选)
+  // final List<WebSocket> _activeSockets = [];
+  // 请求处理器
+  HttpRequestHandler? _requestHandler;
+
+  HttpServerWrap();
+
+
+  // 启动服务器
+  Future<void> start({int port = 8080, HttpRequestHandler? requestHandler}) async {
+    if (_status == HttpServerStatus.starting ||
+        _status == HttpServerStatus.started ||
+        _status == HttpServerStatus.stopping) {
+      return;
+    }
+    _requestHandler = requestHandler;
+    _updateStatus(HttpServerStatus.starting);
+
+    try {
+      _server = await HttpServer.bind(InternetAddress.anyIPv4, port);
+      _serverAddress = 'http://${_server?.address.host}:$port';
+      _updateStatus(HttpServerStatus.started);
+      // Log.d('🚀 HTTP 服务器已启动: $_serverAddress');
+
+      await for (HttpRequest request in _server!) {
+        _handleRequest(request);
+      }
+    } catch (error) {
+      // Log.e('$error');
+      _updateStatus(HttpServerStatus.stopped, message: '$error');
+    }
+  }
+
+  Future<void> _handleRequest(HttpRequest request) async {
+    try {
+      final clientInfo = '🔌 请求来自: ${request.connectionInfo?.remoteAddress} ${request.method} ${request.uri}';
+      _eventController.add(clientInfo);
+
+      if (_requestHandler != null) {
+        await _requestHandler!(request);
+      } else {
+        // 默认响应
+        request.response
+          ..statusCode = HttpStatus.ok
+          ..headers.contentType = ContentType.json
+          ..write(jsonEncode({'message': 'Hello from test server'}))
+          ..close();
+      }
+    } catch (e) {
+      request.response
+        ..statusCode = HttpStatus.internalServerError
+        ..write('Error processing request: $e')
+        ..close();
+    }
+  }
+
+
+  // 停止服务器
+  Future<void> stop() async {
+    _updateStatus(HttpServerStatus.stopping);
+    await _server?.close();
+    _updateStatus(HttpServerStatus.stopped);
+    _server = null;
+    _serverAddress = null;
+    // Log.d('🛑 WebSocket 服务器已停止');
+  }
+
+  void _updateStatus(HttpServerStatus status, {String? message}) {
+    _status = status;
+    String statusStr = '';
+    switch (status) {
+      case HttpServerStatus.starting:
+        statusStr = '正在启动...';
+        break;
+      case HttpServerStatus.started:
+        statusStr = '🚀 服务器已启动,监听端口: $_serverAddress';
+        break;
+      case HttpServerStatus.stopping:
+        statusStr = '正在关闭...';
+        break;
+      case HttpServerStatus.stopped:
+        statusStr = '🛑 服务器已关闭';
+        if (message != null) {
+          statusStr += ': $message';
+        }
+        break;
+    }
+    _eventController.add(statusStr);
+  }
+
+
+}

+ 170 - 0
lib/network/websocketClientWrap.dart

@@ -0,0 +1,170 @@
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+
+enum WebSocketStatus {
+  connecting,
+  connected,
+  disconnected,
+  error,
+}
+
+
+typedef WebSocketMessageHandler = void Function(dynamic message);
+typedef WebSocketStatusHandler = void Function(WebSocketStatus status);
+
+class WebsocketClientWrap {
+  final String url;
+  final Duration reconnectInterval;
+  final Map<String, String>? headers;
+
+  WebSocket? _webSocket;
+  StreamSubscription? _subscription;
+  Timer? _reconnectTimer;
+  bool _disposed = false;
+
+  WebSocketStatus _status = WebSocketStatus.disconnected;
+  WebSocketStatus get status => _status;
+
+  final List<WebSocketMessageHandler> _messageHandlers = [];
+  final List<WebSocketStatusHandler> _statusHandlers = [];
+
+  WebsocketClientWrap({
+    required this.url,
+    this.reconnectInterval = const Duration(seconds: 5),
+    this.headers,
+  });
+
+  /// 连接 WebSocket
+  Future<void> connect() async {
+    if (_disposed) {
+      throw StateError('WebSocket has been disposed');
+    }
+
+    if (_status == WebSocketStatus.connected ||
+        _status == WebSocketStatus.connecting) {
+      return;
+    }
+
+    _updateStatus(WebSocketStatus.connecting);
+
+    try {
+      _webSocket = await WebSocket.connect(url, headers: headers);
+      _updateStatus(WebSocketStatus.connected);
+
+      _subscription = _webSocket!.listen(
+        _handleMessage,
+        onError: _handleError,
+        onDone: _handleDone,
+      );
+
+      // 取消重连定时器
+      _reconnectTimer?.cancel();
+      _reconnectTimer = null;
+    } catch (e) {
+      _handleError(e);
+      _scheduleReconnect();
+    }
+  }
+
+  /// 断开连接
+  Future<void> disconnect() async {
+    _reconnectTimer?.cancel();
+    _reconnectTimer = null;
+
+    await _subscription?.cancel();
+    _subscription = null;
+
+    await _webSocket?.close();
+    _webSocket = null;
+
+    _updateStatus(WebSocketStatus.disconnected);
+  }
+
+  /// 发送消息
+  void send(dynamic message) {
+    if (_status != WebSocketStatus.connected || _webSocket == null) {
+      throw StateError('WebSocket is not connected');
+    }
+
+    if (message is String) {
+      _webSocket!.add(message);
+    } else if (message is Map || message is List) {
+      _webSocket!.add(jsonEncode(message));
+    } else {
+      _webSocket!.add(message.toString());
+    }
+  }
+
+  /// 添加消息监听器
+  void addMessageListener(WebSocketMessageHandler handler) {
+    _messageHandlers.add(handler);
+  }
+
+  /// 移除消息监听器
+  void removeMessageListener(WebSocketMessageHandler handler) {
+    _messageHandlers.remove(handler);
+  }
+
+  /// 添加状态监听器
+  void addStatusListener(WebSocketStatusHandler handler) {
+    _statusHandlers.add(handler);
+  }
+
+  /// 移除状态监听器
+  void removeStatusListener(WebSocketStatusHandler handler) {
+    _statusHandlers.remove(handler);
+  }
+
+  /// 释放资源
+  Future<void> dispose() async {
+    _disposed = true;
+    await disconnect();
+    _messageHandlers.clear();
+    _statusHandlers.clear();
+  }
+
+  void _handleMessage(dynamic message) {
+    try {
+      // 尝试解析 JSON 消息
+      final decoded = jsonDecode(message);
+      for (final handler in _messageHandlers) {
+        handler(decoded);
+      }
+    } catch (e) {
+      // 如果不是 JSON,直接传递原始消息
+      for (final handler in _messageHandlers) {
+        handler(message);
+      }
+    }
+  }
+
+  void _handleError(dynamic error) {
+    _updateStatus(WebSocketStatus.error);
+    _scheduleReconnect();
+  }
+
+  void _handleDone() {
+    if (_status != WebSocketStatus.disconnected && !_disposed) {
+      _updateStatus(WebSocketStatus.disconnected);
+      _scheduleReconnect();
+    }
+  }
+
+  void _scheduleReconnect() {
+    if (_disposed || _reconnectTimer != null) return;
+
+    _reconnectTimer = Timer(reconnectInterval, () {
+      _reconnectTimer = null;
+      connect();
+    });
+  }
+
+  void _updateStatus(WebSocketStatus status) {
+    _status = status;
+    for (final handler in _statusHandlers) {
+      handler(status);
+    }
+  }
+}

+ 115 - 0
lib/network/websocketServerWrap.dart

@@ -0,0 +1,115 @@
+
+import 'dart:async';
+import 'dart:io';
+// import '../util/logger.dart';
+
+
+enum WebsocketServerStatus {
+  starting,
+  started,
+  stopping,
+  stopped,
+}
+
+typedef WebSocketMessageHandler = void Function(dynamic message);
+typedef WebSocketStatusHandler = void Function(WebsocketServerStatus status);
+
+
+class WebsocketServerWrap {
+
+  HttpServer? _server;
+
+  WebsocketServerStatus _status = WebsocketServerStatus.stopped;
+  WebsocketServerStatus get status => _status;
+
+  String? _serverAddress;
+  String? get serverAddress => _serverAddress;
+
+  // 用于向 UI 推送事件
+  final StreamController<String> _eventController = StreamController.broadcast();
+  Stream<String> get events => _eventController.stream;
+
+  // 保存所有活跃的客户端连接(可选)
+  final List<WebSocket> _activeSockets = [];
+
+  WebsocketServerWrap();
+
+
+  // 启动服务器
+  Future<void> start({int port = 8080}) async {
+    if (_status == WebsocketServerStatus.starting ||
+        _status == WebsocketServerStatus.started ||
+        _status == WebsocketServerStatus.stopping) {
+      return;
+    }
+    _updateStatus(WebsocketServerStatus.starting);
+
+    try {
+      _server = await HttpServer.bind(InternetAddress.anyIPv4, port);
+      _serverAddress = 'ws://${_server?.address.host}:$port';
+      _updateStatus(WebsocketServerStatus.started);
+      // Log.d('🚀 WebSocket 服务器已启动: ws://${_server?.address.host}:$port');
+
+      await for (HttpRequest request in _server!) {
+        if (WebSocketTransformer.isUpgradeRequest(request)) {
+          final socket = await WebSocketTransformer.upgrade(request);
+          _handleNewConnection(socket, request);
+        }
+      }
+    } catch (error) {
+      // Log.e('$error');
+    }
+  }
+
+
+  void _handleNewConnection(WebSocket socket, HttpRequest request) {
+    final clientInfo = '🔌 客户端连接: ${request.connectionInfo?.remoteAddress}';
+    _eventController.add(clientInfo);
+    _activeSockets.add(socket); // 记录活跃连接
+
+    socket.listen((message) {
+      final msgLog = '📩 ${request.connectionInfo?.remoteAddress}: $message';
+      _eventController.add(msgLog);
+    },
+      onDone: () {
+        _eventController.add('❌ 客户端断开: ${request.connectionInfo?.remoteAddress}');
+        _activeSockets.remove(socket); // 移除断开连接
+      },
+    );
+  }
+
+
+  // 停止服务器
+  Future<void> stop() async {
+    _updateStatus(WebsocketServerStatus.stopping);
+    await _server?.close();
+    // _eventController.add('🛑 服务器已停止');
+    _activeSockets.clear(); // 清空所有连接
+    _updateStatus(WebsocketServerStatus.stopped);
+    _server = null;
+    _serverAddress = null;
+    // Log.d('🛑 WebSocket 服务器已停止');
+  }
+
+  void _updateStatus(WebsocketServerStatus status) {
+    _status = status;
+    String statusStr = '';
+    switch (status) {
+      case WebsocketServerStatus.starting:
+        statusStr = '正在启动...';
+        break;
+      case WebsocketServerStatus.started:
+        statusStr = '🚀 服务器已启动,监听端口: $_serverAddress';
+        break;
+      case WebsocketServerStatus.stopping:
+        statusStr = '正在关闭...';
+        break;
+      case WebsocketServerStatus.stopped:
+        statusStr = '🛑 服务器已关闭';
+        break;
+    }
+    _eventController.add(statusStr);
+  }
+
+
+}