Flutter开发进阶之使用Socket实现主机服务(一)

Flutter开发进阶之使用Socket实现主机服务(一)

在Flutter开发实践中,有一些业务是需要主从机合作搭配的服务,其中一些重要的数据和功能是交由主机进行存储和管理,从机再通过UDP和TCP与主机通讯去获得权限,一般在同一个局域网内的多端实现。
Flutter开发

广播

在主从机未建立联系之前,主从机除了自身的权限是已知的是不知道任何其他设备的信息的,这时候就需要利用到UDP的广播,因为在局域网中,UDP广播是一种允许设备向网络中的所有其他设备发送消息的技术;
广播地址通常是255.255.255.255,或者网络地址和主机地址的组合,主从机约定好广播的端口后,主机需要监听指定端口的UDP广播。

  void udp_listen() async {
    // 监听所有可用地址5000端口的广播
    _socket = await RawDatagramSocket.bind("0.0.0.0", 5000);
    _socket?.listen((event) {
      switch (event) {
        case RawSocketEvent.read:
          Datagram? datagram = _socket?.receive();
          if (datagram != null) {
            const decoder = Utf8Decoder();
            print(decoder.convert(datagram.data));
            // 获取到广播信息,内容可能包括指定的加密后信息,可以是广播类型或者IP地址等
          }
          break;
        case RawSocketEvent.write:
          break;
        case RawSocketEvent.readClosed:
          break;
        case RawSocketEvent.closed:
          break;
      }
    }, onDone: () {
      _socket?.close();
      _socket = null;
    });
  }

主机开启监听后,从机可以发送广播了。

void udp_send() async {
    _socket = await RawDatagramSocket.bind("0.0.0.0", 5000);
    var message = "xxxxxxxxxx";
    final data = Uint8List.fromList(message.codeUnits);
    await _socket?.send(data, InternetAddress.anyIPv4, 5000);
  }

此时主从机已经完成了数据交互,主机已获知了从机的相关信息,可以建立指定的广播或者直接建立TCP通讯了;
此时我们可以使用flutter_socket_io库进行TCP通信,可以通过创建自定义的连接池来管理连接,连接池可以帮助你重用现有的连接,而不是为每个请求创建新的连接,从而提高性能和效率。

连接池

dependencies:  
  flutter_socket_io: ^latest_version

创建一个自定义的连接池类,这个类将负责管理连接的生命周期和重用现有的连接。

class ConnectionPool {  
  final int maxConnections = 5; // 设置最大连接数  
  final String host = '127.0.0.1'; // 设置服务器地址  
  final int port = 8080; // 设置服务器端口  
  
  Map<int, Socket> _pool = {}; // 用于存储连接的映射  
  int _nextId = 0; // 用于生成唯一的连接ID  
  
  Socket getConnection() {  
    int id = _nextId++;  
    Socket socket = Socket.fromAddress(host, port);  
    _pool[id] = socket;  
    return socket;  
  }  
  
  void releaseConnection(Socket socket) {  
    // 在这里实现连接释放的逻辑,例如关闭连接等操作  
  }  
}

收发消息

以下是一些简单的示例,实际开发中还需注意后续的线程安全、各种网络异常等问题。

Socket socket = connectionPool.getConnection();
socket.listen((data) {  
  print('Received: $data');  
});
Future<String> sendMessage(String message) async {  
    try {  
      Socket socket = connectionPool.getConnection(); // 获取连接  
      // 使用socket发送消息并处理响应  
      socket.write('你要发送的消息');
      // ...  
      socket.close(); // 释放连接  
      return 'Message sent successfully';  
    } catch (e) {  
      print('Error sending message: ${e.toString()}');  
      return 'Failed to send message';  
    }  
  }  
  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用 Flutter 的 go_router 进行进阶使用时,您可以探索以下功能和技巧: 1. 命名路由:除了使用路径来导航页面,go_router 还支持命名路由,通过给每个路由规则指定一个唯一的名称,可以更方便地进行页面跳转。例如: ```dart final routes = [ GoRoute( path: '/', pageBuilder: (context, state) => HomePage(), name: 'home', ), GoRoute( path: '/details/:id', pageBuilder: (context, state) => DetailsPage(id: state.params['id']), name: 'details', ), ]; ``` 然后,您可以通过名称进行页面跳转: ```dart GoRouter.of(context).goNamed('details', params: {'id': '123'}); ``` 2. 参数传递:go_router 允许您在页面之间传递参数。在路由规则中,可以定义参数占位符,然后在页面构建器中获取这些参数并使用它们。例如: ```dart final routes = [ GoRoute( path: '/details/:id', pageBuilder: (context, state) => DetailsPage(id: state.params['id']), ), ]; ``` 在 DetailsPage 中可以通过 `widget.id` 访问传递的参数。 3. 路由拦截和重定向:go_router 允许您在路由跳转之前进行拦截和处理。您可以使用 `beforeEnter` 方法来拦截特定的路由,并根据需要执行操作,例如权限验证、参数校验等。还可以使用 `redirectTo` 方法来重定向到其他路由。例如: ```dart final routes = [ GoRoute( path: '/details/:id', pageBuilder: (context, state) => DetailsPage(id: state.params['id']), beforeEnter: (context, state) { // 进行权限验证或其他操作 if (!isLoggedIn) { return redirectTo('/login'); } return null; }, ), ]; ``` 4. 页面切换动画:go_router 支持自定义页面切换动画,您可以为每个路由规则定义不同的动画效果。使用 `transitionDuration` 和 `transitionBuilder` 属性来自定义页面切换动画。例如: ```dart final routes = [ GoRoute( path: '/', pageBuilder: (context, state) => HomePage(), transitionDuration: Duration(milliseconds: 500), transitionBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition(opacity: animation, child: child); }, ), ]; ``` 在上述示例中,我们使用了一个渐变的动画效果。 这些是 go_router 的一些进阶使用方法,您可以根据您的实际需求来灵活使用它们。请参考 go_router 的官方文档以获取更多详细信息和示例代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值