You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何重构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');
      });
}

关键修复说明

  1. 客户端:

    • 用socket.add()替代socket.write(),直接发送原始字节流,避免编码干扰
    • 监听文件流onDone事件,发送完成后主动关闭Socket,让服务器及时感知传输结束
    • 增加错误处理分支,读取文件失败时及时关闭连接
  2. 服务器端:

    • 先收集所有接收的字节,再统一转换为字符串,彻底解决分块导致的乱码问题
    • 使用sink.add()写入文件,匹配二进制流的写入逻辑
    • 给utf8.decode()添加allowMalformed参数,兼容可能的编码异常,避免转换崩溃

内容的提问来源于stack exchange,提问作者Mr.Nima

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:07:36