Flutter 中的 TCP

在移动应用开发中,TCP 协议因其可靠的面向连接特性,广泛应用于实时通讯、设备控制、数据同步等场景。Flutter 作为跨平台框架,通过 Dart 语言的dart:io库原生支持 TCP 编程,无需依赖第三方插件即可实现完整的客户端 / 服务器交互。

一、核心技术栈与原理

1.1 关键依赖库​

  • dart:io:提供Socket(客户端)和ServerSocket(服务器)类,是 TCP 通讯的核心 API
  • dart:convert:用于 UTF-8 数据编码解码,处理二进制数据与字符串的转换
  • dart:async:支持异步编程(async/await),处理 TCP 连接、数据收发等异步操作
  • Flutter UI 组件:StatefulWidget(状态管理)、TextField(输入)、ListView(消息展示)等

1.2 TCP 通讯核心原理​

  1. 客户端流程:建立连接(Socket.connect)→ 发送数据(socket.write)→ 监听接收数据(socket.listen)→ 断开连接(socket.close)
  2. 服务器流程:绑定端口(ServerSocket.bind)→ 监听客户端连接(await for)→ 处理客户端消息(handleClient)→ 回复数据
  3. 状态管理:通过setState更新连接状态、消息列表等 UI 展示

二、完整实现:Flutter TCP 客户端​

2.1 项目结构与核心变量​

客户端采用StatefulWidget管理动态状态,核心变量包括:

dart 复制代码
Socket? _socket; // TCP连接对象
bool _isConnected = false; // 连接状态标记
String _status = '未连接'; // 状态文本
Listmessages = []; // 消息历史列表

// 输入控制器(IP、端口、消息)
final TextEditingController _ipController = TextEditingController(text: '127.0.0.1');
final TextEditingController _portController = TextEditingController(text: '8080');
final TextEditingController _messageController = TextEditingController();

2.2 核心功能实现​

(1)连接 TCP 服务器

dart 复制代码
/// 连接到TCP服务器
  /// 
  /// 功能:
  /// 1. 更新UI显示连接中状态
  /// 2. 尝试与指定IP和端口的服务器建立TCP连接
  /// 3. 连接成功后更新UI状态并开始监听服务器消息
  /// 4. 处理连接错误和异常
  /// 
  /// 返回值:
  /// - Future<void>: 异步操作,无返回值
  Future<void> _connectToServer() async {
    try {
      // 更新UI状态为连接中
      setState(() {
        _status = '连接中...';
      });
      
      // 建立TCP连接
      // 参数说明:
      // - host: 服务器IP地址,从输入框获取
      // - port: 服务器端口,从输入框获取并转换为整数
      // - timeout: 连接超时时间,设置为5秒
      _socket = await Socket.connect(
        _ipController.text,          // 服务器IP地址
        int.parse(_portController.text),  // 服务器端口
        timeout: const Duration(seconds: 5),  // 连接超时时间
      );
      
      // 连接成功,更新UI状态
      setState(() {
        _isConnected = true;         // 设置连接状态为已连接
        _status = '已连接';          // 更新状态文本
        _messages.add('已连接到服务器');  // 添加连接成功消息
      });
      
      // 开始监听Socket事件
      _socket!.listen(
        // 收到数据时的回调函数
        (List<int> data) {
          // 将接收到的二进制数据转换为字符串
          final message = utf8.decode(data);
          
          // 更新UI,添加服务器消息
          setState(() {
            _messages.add('服务器: $message');
          });
        },
        
        // 发生错误时的回调函数
        onError: (error) {
          // 更新UI状态为错误
          setState(() {
            _isConnected = false;       // 设置连接状态为未连接
            _status = '连接错误';       // 更新状态文本
            _messages.add('错误: $error');  // 添加错误消息
          });
          
          // 关闭Socket连接
          _socket?.close();
        },
        
        // 连接关闭时的回调函数
        onDone: () {
          // 更新UI状态为连接关闭
          setState(() {
            _isConnected = false;       // 设置连接状态为未连接
            _status = '连接关闭';       // 更新状态文本
            _messages.add('连接已关闭');  // 添加连接关闭消息
          });
          
          // 关闭Socket连接
          _socket?.close();
        },
      );
    } catch (e) {
      // 捕获连接过程中的异常
      setState(() {
        _status = '连接失败';          // 更新状态文本为连接失败
        _messages.add('错误: $e');      // 添加错误消息
      });
    }
  }

(2)断开连接与发送消息

dart 复制代码
// 断开连接

  /// 断开与TCP服务器的连接
  /// 
  /// 功能:
  /// 1. 关闭当前的Socket连接
  /// 2. 更新UI状态为未连接
  /// 3. 添加断开连接消息到消息列表
  void _disconnectFromServer() {
    // 关闭Socket连接
    _socket?.close();
    
    // 更新UI状态
    setState(() {
      _isConnected = false;         // 设置连接状态为未连接
      _status = '未连接';           // 更新状态文本
      _messages.add('已断开连接');    // 添加断开连接消息
    });
  }

  /// 发送消息到TCP服务器
  /// 
  /// 功能:
  /// 1. 检查当前是否已连接到服务器
  /// 2. 获取输入框中的消息内容
  /// 3. 发送消息到服务器(添加换行符便于服务器处理)
  /// 4. 更新UI,添加发送的消息到消息列表
  /// 5. 清空消息输入框
  void _sendMessage() {
    // 检查连接状态
    if (_socket != null && _isConnected) {
      // 获取输入的消息
      final message = _messageController.text;
      
      // 发送消息到服务器,添加换行符便于服务器处理
      _socket!.write('$message\n');
      
      // 更新UI,添加发送的消息
      setState(() {
        _messages.add('客户端: $message');  // 添加客户端消息
        _messageController.clear();        // 清空输入框
      });
    }
  }

三、配套 TCP 服务器实现(Dart)​

为了测试客户端,我们用 Dart 编写一个简单的 TCP 服务器,监听 8080 端口:

dart 复制代码
import 'dart:io'; // 提供Socket和网络功能
import 'dart:core'; // 提供Dart核心功能

/// TCP服务器示例
///
/// 功能:
/// 1. 监听本地8080端口,接收TCP客户端连接
/// 2. 处理客户端发送的消息,解码并打印
/// 3. 回复客户端消息,确认收到
/// 4. 处理连接错误和异常
/// 5. 提供详细的日志输出,便于调试
///
/// 技术要点:
/// - 使用dart:io库的ServerSocket类创建TCP服务器
/// - 使用await for循环监听客户端连接
/// - 使用Socket.listen()方法监听Socket事件
/// - 使用try-catch处理异常
/// - 使用DateTime.now()添加时间戳日志

/// 服务器主函数
/// 功能:启动TCP服务器,监听客户端连接
///
void main() async {
  try {
    // 绑定服务器地址和端口
    // 参数说明:
    // - address: 服务器地址,'127.0.0.1'表示本地地址
    // - port: 服务器端口,8080是常用测试端口
    // 返回值:
    // - ServerSocket实例,用于监听客户端连接
    final server = await ServerSocket.bind('127.0.0.1', 8080);

    // 持续监听客户端连接
    // await for循环会自动处理异步流,每次有新连接时执行循环体
    await for (var socket in server) {
      // 为每个客户端创建一个处理函数
      handleClient(socket);
    }
  } catch (e) {
    // 捕获启动服务器时的错误
    print('${DateTime.now()} - 启动服务器时出错: $e');
  }
}

/// 处理客户端连接
/// 功能:处理单个客户端的消息收发和连接管理
///
/// 参数:
/// - socket: Socket对象,表示与客户端的连接
///
/// 执行流程:
/// 1. 获取客户端地址和端口信息
/// 2. 打印客户端连接信息
/// 3. 监听Socket事件(数据接收、错误、关闭)
/// 4. 处理接收到的消息,解码并回复
/// 5. 处理连接错误和异常
/// 6. 处理连接关闭事件
void handleClient(Socket socket) {
  // 构建客户端地址和端口的字符串表示
  final clientAddr = '${socket.remoteAddress.address}:${socket.remotePort}';

  // 监听Socket事件
  socket.listen(
    // 收到数据时的回调函数
    // 参数:
    // - data: List<int>类型,表示接收到的二进制数据
    (List<int> data) {
      try {
        // 尝试将二进制数据转换为字符串
        // 使用String.fromCharCodes()方法解码,然后去除首尾空白字符
        final message = String.fromCharCodes(data, 0, data.length).trim();

        // 构建回复消息,添加换行符便于客户端处理
        final response = '服务器收到: $message\n';

        // 发送回复给客户端
        socket.write(response);
      } catch (e) {
        // 构建错误回复消息
        final response = '解码错误\n';

        // 发送错误回复给客户端
        socket.write(response);
      }
    },

    // 发生错误时的回调函数
    // 参数:
    // - error: 错误对象,表示发生的错误
    onError: (error) {
      // 打印处理客户端错误的日志
      print('${DateTime.now()} - 处理客户端 $clientAddr 时出错: $error');
      // 关闭客户端连接
      socket.close();
    },

    // 连接关闭时的回调函数
    onDone: () {
      // 打印客户端连接关闭的日志
      print('${DateTime.now()} - 客户端 $clientAddr 连接已关闭');

      // 关闭客户端连接
      socket.close();
    },
  );
}

四、实战测试步骤​

4.1 运行服务器​

  1. 创建server.dart文件,复制上述服务器代码
  2. 终端执行:dart server.dart,启动服务器(显示 "服务器启动,监听 127.0.0.1:8080" 即为成功)

4.2 运行 Flutter 客户端​

  1. 创建 Flutter 项目:flutter create tcp_demo
  2. 替换lib/main.dart为客户端代码
  3. 运行项目:flutter run(支持模拟器或真机)
  4. 操作流程:
  • 输入服务器 IP(本地测试用127.0.0.1)和端口(8080)
  • 点击 "连接",状态变为 "已连接"
  • 输入消息,点击 "发送",即可与服务器双向通讯

4.3 预期效果​

  • 客户端发送消息后,消息列表显示 "客户端:消息内容"
  • 服务器收到消息后,终端打印日志,并回复 "服务器收到:消息内容"
  • 客户端接收回复后,消息列表显示 "服务器:回复内容"
  • 断开连接后,双方均会收到连接关闭通知

Flutter 通过 Dart 的dart:io库提供了简洁强大的 TCP 通讯能力,无需依赖第三方插件即可实现客户端与服务器的双向通讯。无论是实时聊天、设备控制还是数据同步场景,Flutter TCP 通讯都能满足需求。

相关推荐
子春一17 小时前
Flutter for OpenHarmony:形状拼图:基于路径几何与空间吸附的交互式拼图系统架构解析
flutter·系统架构
ujainu1 天前
Flutter + OpenHarmony 游戏开发进阶:用户输入响应——GestureDetector 实现点击发射
flutter·游戏·openharmony
hudawei9961 天前
TweenAnimationBuilder和AnimatedBuilder两种动画的比较
flutter·ui·动画·tweenanimation·animatedbuilder
ujainu1 天前
Flutter + OpenHarmony 实现无限跑酷游戏开发实战—— 对象池化、性能优化与流畅控制
flutter·游戏·性能优化·openharmony·endless runner
ZH15455891311 天前
Flutter for OpenHarmony Python学习助手实战:自动化脚本开发的实现
python·学习·flutter
晚烛1 天前
CANN + 物理信息神经网络(PINNs):求解偏微分方程的新范式
javascript·人工智能·flutter·html·零售
一起养小猫1 天前
Flutter for OpenHarmony 实战:扫雷游戏完整开发指南
flutter·harmonyos
晚烛1 天前
CANN 赋能智慧医疗:构建合规、高效、可靠的医学影像 AI 推理系统
人工智能·flutter·零售
晚霞的不甘1 天前
揭秘 CANN 内存管理:如何让大模型在小设备上“轻装上阵”?
前端·数据库·经验分享·flutter·3d