直接上代码:
/// @Author: Hui_Loading 3080811164@qq.com
/// @Date: 2025-02-22 12:42:38
/// @LastEditors: Hui_Loading 3080811164@qq.com
/// @LastEditTime: 2025-02-23 18:51:43
/// @FilePath: lib/Tools/Websocket/temp.dart
/// @Description: 这是websocket链接测试
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'dart:convert';
import '../Login_status_review/login_prefs.dart'; // 用于 JSON 编码
class MyApp_socketTest extends StatelessWidget {
const MyApp_socketTest({super.key});
@override
Widget build(BuildContext context) {
const title = 'WebSocket 连接测试';
return const MaterialApp(
title: title,
home: MyHomePage(title: title),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
///添加了心跳机制
class _MyHomePageState extends State<MyHomePage> {
final TextEditingController _controller = TextEditingController();
WebSocketChannel? _channel;
bool _isConnected = false;
bool _isConnecting = false;
late Stream? _broadcastStream;
int _reconnectAttempt = 0; // 记录重连次数
Timer? _heartbeatTimer;
@override
void initState() {
super.initState();
print("[WebSocket] 初始化状态");
_connectWebSocket();
}
Future<void> _connectWebSocket() async {
if (_isConnecting || _isConnected) {
print("[WebSocket] 连接已存在或正在连接中,取消重复连接");
return;
}
print("[WebSocket] 开始连接尝试 (第${_reconnectAttempt + 1}次)");
setState(() => _isConnecting = true);
try {
final String token = await LoginPrefs.getToken() ?? 'null';
print("[WebSocket] 获取到Token: ${token.substring(0, 15)}..."); // 避免打印完整token
final uri = Uri.parse('ws://xxxxxxxxxxxx?x-token=${token}');
print("[WebSocket] 正在连接至: ${uri.toString().replaceAll(token, "[TOKEN]")}"); // 隐藏敏感信息
final startTime = DateTime.now();
final webSocket = await WebSocket.connect(
uri.toString(),
headers: {'x-token': token},
).timeout(const Duration(seconds: 10)); // 添加超时控制
print("[WebSocket] 连接建立成功,耗时: ${DateTime.now().difference(startTime).inMilliseconds}ms");
print("[WebSocket] 协议版本: ${webSocket.protocol}");
_channel = IOWebSocketChannel(webSocket);
_broadcastStream = _channel?.stream.asBroadcastStream();
setState(() {
_isConnected = true;
_isConnecting = false;
_reconnectAttempt = 0; // 重置重连计数器
});
print("[WebSocket] 连接状态更新: connected=$_isConnected");
print("[WebSocket] 开启消息监听...");
_broadcastStream?.listen(
(data) {
print("[WebSocket] <<< 接收消息 [${DateTime.now().toIso8601String()}]");
print("消息原始数据: $data");
try {
final jsonData = jsonDecode(data);
print("解析后的JSON: $jsonData");
if (jsonData['type'] == 'pong') {
_handleHeartbeatResponse(jsonData); // 处理心跳响应
} else {
Fluttertoast.showToast(msg: "收到消息: ${jsonData['msgContent'] ?? data}");
}
} catch (e) {
print("消息解析失败: $e");
}
},
onError: (error) {
print("[WebSocket] !!! 流错误 [${DateTime.now().toIso8601String()}]");
print("错误详情: $error");
if (error is WebSocketException) {
print("WebSocket异常详情:");
print("状态码: ${error.hashCode}");
print("原因: ${error.message}");
}
_handleDisconnect();
},
onDone: () {
print("[WebSocket] ### 连接关闭 [${DateTime.now().toIso8601String()}]");
print("关闭原因: ${webSocket.closeReason}");
print("关闭代码: ${webSocket.closeCode}");
_handleDisconnect();
},
cancelOnError: true,
);
// 启动心跳定时器
_startHeartbeat();
} on WebSocketException catch (e) {
print("[WebSocket] !!! WebSocket异常: ${e.toString()}");
print("状态码: ${e.hashCode}");
print("原因: ${e.message}");
_handleDisconnect();
} on TimeoutException {
print("[WebSocket] !!! 连接超时");
_handleDisconnect();
} catch (e, stackTrace) {
print("[WebSocket] !!! 连接异常: ${e.toString()}");
print("堆栈跟踪: $stackTrace");
_handleDisconnect();
} finally {
if (!_isConnected) {
_reconnectAttempt++;
print("[WebSocket] 将在5秒后尝试第$_reconnectAttempt次重连...");
await Future.delayed(const Duration(seconds: 5));
_connectWebSocket();
}
}
}
void _startHeartbeat() {
if (_heartbeatTimer == null) {
_heartbeatTimer = Timer.periodic(const Duration(seconds: 10), (timer) {
if (_isConnected && _channel?.sink != null) {
final heartbeatPayload = jsonEncode({'type': 'ping'});
print("[WebSocket] >>> 发送心跳 [${DateTime.now().toIso8601String()}]");
_channel!.sink.add(heartbeatPayload);
}
});
}
}
void _handleHeartbeatResponse(dynamic data) {
print("[WebSocket] 心跳响应已处理: $data");
}
void _handleDisconnect() {
if (_isConnected || _isConnecting) {
print("[WebSocket] 处理断开连接...");
print("当前连接状态: connected=$_isConnected, connecting=$_isConnecting");
setState(() {
_isConnected = false;
_isConnecting = false;
});
_channel?.sink.close();
_channel = null;
}
if (_heartbeatTimer != null) {
_heartbeatTimer?.cancel();
_heartbeatTimer = null;
}
print("[WebSocket] 连接资源已释放");
}
void _sendMessage() {
if (!_isConnected || _channel?.sink == null) {
print("[WebSocket] 发送失败:连接不可用");
return;
}
final message = _controller.text;
if (message.isEmpty) {
print("[WebSocket] 发送失败:消息内容为空");
return;
}
final String _targetId = 'your Id';
final String _userId = LoginPrefs.getUserID() ?? "null";
final payload = {
"targetId": _targetId,
"source": "user",
"msgContent": message,
"userId": _userId,
"type": "text",
};
try {
print("[WebSocket] >>> 发送消息 [${DateTime.now().toIso8601String()}]");
print("消息原始内容: $message");
print("完整Payload: $payload");
final jsonString = jsonEncode(payload);
print("序列化后的JSON: $jsonString");
_channel!.sink.add(jsonString);
print("[WebSocket] 消息发送成功");
} catch (e, stackTrace) {
print("[WebSocket] !!! 消息发送失败");
print("错误详情: $e");
print("堆栈跟踪: $stackTrace");
}
_controller.clear();
}
@override
void dispose() {
print("[WebSocket] 组件销毁,释放资源");
_channel?.sink.close();
_heartbeatTimer?.cancel();
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
print("[UI] 构建界面,当前状态: connected=$_isConnected, connecting=$_isConnecting");
return Scaffold(
appBar: AppBar(
title: Row(
children: [
Text(widget.title),
Icon(
_isConnected ? Icons.cloud_done : Icons.cloud_off,
color: _isConnected ? Colors.green : Colors.red,
),
],
),
),
body: _isConnected
? _buildConnectedUI()
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (_isConnecting) CircularProgressIndicator(),
Text(_isConnecting ? '正在连接中...' : '连接已断开'),
],
),
),
floatingActionButton: _isConnected
? FloatingActionButton(
onPressed: _sendMessage,
tooltip: '发送消息',
child: const Icon(Icons.send),
)
: null,
);
}
Widget _buildConnectedUI() {
return Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
TextFormField(
controller: _controller,
decoration: const InputDecoration(labelText: '发送一条文字消息'),
),
const SizedBox(height: 24),
Expanded(
child: StreamBuilder(
stream: _broadcastStream,
builder: (context, snapshot) {
print("[StreamBuilder] 重建,状态: ${snapshot.connectionState}");
if (snapshot.hasError) {
print("[StreamBuilder] 包含错误: ${snapshot.error}");
return Center(
child: Text('错误: ${snapshot.error}'),
);
}
if (snapshot.connectionState == ConnectionState.done) {
return const Center(child: Text('连接已关闭'));
}
return ListView(
children: [
if (snapshot.hasData && snapshot.data is String) ...[
const SizedBox(height: 16),
Text('收到消息: ${snapshot.data}'),
],
],
);
},
),
)
],
),
);
}
}
如有任何问题,欢迎私信或发送邮件讨论,我的邮箱:
3080811164@qq.com