websocketClientWrap.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. enum WebSocketStatus {
  5. connecting,
  6. connected,
  7. disconnected,
  8. error,
  9. }
  10. typedef WebSocketMessageHandler = void Function(dynamic message);
  11. typedef WebSocketStatusHandler = void Function(WebSocketStatus status);
  12. class WebsocketClientWrap {
  13. final String url;
  14. final Duration reconnectInterval;
  15. final Map<String, String>? headers;
  16. WebSocket? _webSocket;
  17. StreamSubscription? _subscription;
  18. Timer? _reconnectTimer;
  19. bool _disposed = false;
  20. WebSocketStatus _status = WebSocketStatus.disconnected;
  21. WebSocketStatus get status => _status;
  22. final List<WebSocketMessageHandler> _messageHandlers = [];
  23. final List<WebSocketStatusHandler> _statusHandlers = [];
  24. WebsocketClientWrap({
  25. required this.url,
  26. this.reconnectInterval = const Duration(seconds: 5),
  27. this.headers,
  28. });
  29. /// 连接 WebSocket
  30. Future<void> connect() async {
  31. if (_disposed) {
  32. throw StateError('WebSocket has been disposed');
  33. }
  34. if (_status == WebSocketStatus.connected ||
  35. _status == WebSocketStatus.connecting) {
  36. return;
  37. }
  38. _updateStatus(WebSocketStatus.connecting);
  39. try {
  40. _webSocket = await WebSocket.connect(url, headers: headers);
  41. _updateStatus(WebSocketStatus.connected);
  42. _subscription = _webSocket!.listen(
  43. _handleMessage,
  44. onError: _handleError,
  45. onDone: _handleDone,
  46. );
  47. // 取消重连定时器
  48. _reconnectTimer?.cancel();
  49. _reconnectTimer = null;
  50. } catch (e) {
  51. _handleError(e);
  52. _scheduleReconnect();
  53. }
  54. }
  55. /// 断开连接
  56. Future<void> disconnect() async {
  57. _reconnectTimer?.cancel();
  58. _reconnectTimer = null;
  59. await _subscription?.cancel();
  60. _subscription = null;
  61. await _webSocket?.close();
  62. _webSocket = null;
  63. _updateStatus(WebSocketStatus.disconnected);
  64. }
  65. /// 发送消息
  66. void send(dynamic message) {
  67. if (_status != WebSocketStatus.connected || _webSocket == null) {
  68. throw StateError('WebSocket is not connected');
  69. }
  70. if (message is String) {
  71. _webSocket!.add(message);
  72. } else if (message is Map || message is List) {
  73. _webSocket!.add(jsonEncode(message));
  74. } else {
  75. _webSocket!.add(message.toString());
  76. }
  77. }
  78. /// 添加消息监听器
  79. void addMessageListener(WebSocketMessageHandler handler) {
  80. _messageHandlers.add(handler);
  81. }
  82. /// 移除消息监听器
  83. void removeMessageListener(WebSocketMessageHandler handler) {
  84. _messageHandlers.remove(handler);
  85. }
  86. /// 添加状态监听器
  87. void addStatusListener(WebSocketStatusHandler handler) {
  88. _statusHandlers.add(handler);
  89. }
  90. /// 移除状态监听器
  91. void removeStatusListener(WebSocketStatusHandler handler) {
  92. _statusHandlers.remove(handler);
  93. }
  94. /// 释放资源
  95. Future<void> dispose() async {
  96. _disposed = true;
  97. await disconnect();
  98. _messageHandlers.clear();
  99. _statusHandlers.clear();
  100. }
  101. void _handleMessage(dynamic message) {
  102. try {
  103. // 尝试解析 JSON 消息
  104. final decoded = jsonDecode(message);
  105. for (final handler in _messageHandlers) {
  106. handler(decoded);
  107. }
  108. } catch (e) {
  109. // 如果不是 JSON,直接传递原始消息
  110. for (final handler in _messageHandlers) {
  111. handler(message);
  112. }
  113. }
  114. }
  115. void _handleError(dynamic error) {
  116. _updateStatus(WebSocketStatus.error);
  117. _scheduleReconnect();
  118. }
  119. void _handleDone() {
  120. if (_status != WebSocketStatus.disconnected && !_disposed) {
  121. _updateStatus(WebSocketStatus.disconnected);
  122. _scheduleReconnect();
  123. }
  124. }
  125. void _scheduleReconnect() {
  126. if (_disposed || _reconnectTimer != null) return;
  127. _reconnectTimer = Timer(reconnectInterval, () {
  128. _reconnectTimer = null;
  129. connect();
  130. });
  131. }
  132. void _updateStatus(WebSocketStatus status) {
  133. _status = status;
  134. for (final handler in _statusHandlers) {
  135. handler(status);
  136. }
  137. }
  138. }