如何重构Dart中客户端向服务器发送的二进制代码?
Dart 二进制文件传输异常修复方案
原代码核心问题
- 客户端发送完文件后未主动关闭Socket,服务器无法感知传输结束,持续处于等待状态
- 服务器分块接收二进制时直接转字符串,多字节字符会因拆分在不同块中出现乱码
- 客户端用
socket.write()发送二进制,可能触发不必要的编码转换,影响原始字节传输
重构后的客户端代码
import 'dart:io'; void main() async { final socket = await Socket.connect('localhost', 8000); print('Connected to server'); final file = File('D:\\Flutter\\rock_paper_scissors\\assets\\images\\sang.txt'); final stream = file.openRead(); // 直接发送原始字节,避免编码转换干扰 stream.listen( (data) { print('Read data chunk length: ${data.length}'); socket.add(data); }, onDone: () { print('File stream read completed, closing socket'); socket.close(); // 发送完成主动关闭,通知服务器传输结束 }, onError: (e) { print('Error reading file: $e'); socket.close(); }, ); await socket.done; print('Disconnected from server'); }
重构后的服务器端代码
import 'dart:io'; import 'dart:convert'; void main() async { final server = await ServerSocket.bind('localhost', 8000); print('Server started on port ${server.port}'); await for (Socket client in server) { handleClient(client); } } void handleClient(Socket client) async { print('Client connected from: ${client.remoteAddress.address}:${client.remotePort}'); final file = File('D:\\UI\\text.txt'); final sink = file.openWrite(); // 先收集所有字节,再统一转字符串避免分块乱码 final allBytes = <int>[]; await client .listen( (data) { allBytes.addAll(data); sink.add(data); // 直接写入原始字节,保证文件完整性 }, onError: (e) { print('Error receiving data: $e'); }, ) .asFuture() .then((_) async { await sink.close(); client.close(); // 全部字节接收完成后再转换为字符串 final stringData = utf8.decode(allBytes, allowMalformed: true); print('Received complete data: $stringData'); print('Client disconnected'); }); }
关键修复说明
客户端:
- 用
socket.add()替代socket.write(),直接发送原始字节流,避免编码干扰 - 监听文件流
onDone事件,发送完成后主动关闭Socket,让服务器及时感知传输结束 - 增加错误处理分支,读取文件失败时及时关闭连接
- 用
服务器端:
- 先收集所有接收的字节,再统一转换为字符串,彻底解决分块导致的乱码问题
- 使用
sink.add()写入文件,匹配二进制流的写入逻辑 - 给
utf8.decode()添加allowMalformed参数,兼容可能的编码异常,避免转换崩溃
内容的提问来源于stack exchange,提问作者Mr.Nima
相关产品推荐
相关产品推荐

