Flutter网络通信插件utp_protocol的使用

发布于 1周前 作者 bupafengyu 来自 Flutter

Flutter网络通信插件utp_protocol的使用

本库实现了使用纯Dart语言实现的µTorrent传输协议(uTorrent Transport Protocol),无需任何其他本地库。

更多有关uTP的信息,请参阅此文档

如何使用

uTP套接字包括ServerUTPSocketUTPSocketClient

监听传入连接

var serverSocket = await ServerUTPSocket.bind(InternetAddress.anyIPv4, portyoulike);

serverSocket.listen((socket) {
  print('有人连接到我');
  socket.listen((data) {
    // 接收数据
  });
});

连接到远程主机

var client = UTPSocketClient();
var socket = await client.connect(remoteAddress, remotePort);

socket.listen((data) {
  // 接收数据
});

每个UTPSocketClient实例可以通过connect方法创建多个uTP套接字,并且每个uTP套接字共享相同的原始UDP套接字。用户可以在创建UTPSocketClient实例时设置最大uTP套接字数量(默认为5)。

发送数据

socket.write(sometext); // 发送一些文本
socket.writeln(sometext); // 发送一些文本并附加换行符
// 将多个文本一起发送,并用逗号分隔
socket.writeAll(sometextList, ',');
socket.add(somebyteslist); // 发送一些List<int>类型的数据

默认文本编码为UTF-8,用户可以设置编码:

socket.encoding = someencoding;

尽管uTP套接字使用UDP来传输数据,但uTP套接字不会逐个发送数据,而是将数据添加到发送缓冲区中。一旦有可用的窗口大小,套接字会从缓冲区读取数据(少于最大数据包大小),然后打包并发送出去。

另一方面,如果在同一个事件循环中调用了发送数据的方法(如addwrite等),这些发送的数据会被添加到一个缓存中,套接字会在下一个事件循环中请求发送它们。

例如:

socket.write('u');
socket.write('T');
socket.write('P';

这些方法在同一事件循环中被调用,这些数据(‘u’、‘T’、‘P’)将被添加到一个缓存中(变成’uTP’),并在下一个事件循环中发送。

但这并不意味着远程端会在一个数据包中接收到’uTP’,这取决于当前的窗口大小。

接收(监听)数据

socket.listen((Uint8List data) {
  // 接收数据
},
onDone: () {
  // 当远程或本地套接字关闭时,调用此方法
},
onError: (e) {
  // 当错误发生时,调用此方法
});

关闭套接字

await socket.close();

当调用close方法时,套接字将向远程端发送ST_FIN消息并等待确认。如果用户希望立即关闭它,可以调用以下方法:

socket.destroy();

实际上,destroy方法会向远程端发送ST_RESET消息,但不会等待确认。

如果套接字关闭,它将等待预期的ACK序列号。当接收到正确的序列号时,close方法将完成未来的操作;否则,它将在超时时完成未来的操作。

示例代码

以下是完整的示例代码:

import 'dart:convert';
import 'dart:io';

import 'package:utp_protocol/src/base/server_utp_socket.dart';
import 'package:utp_protocol/src/utp_socket_client.dart';

void main() async {
  var total = 21889;
  var chinese = '中文字符甲乙丙丁戊己庚辛\n';
  int startTime;
  var ss = await ServerUTPSocket.bind(InternetAddress.anyIPv4, 0);
  var port = ss.port;
  print('[Server] 开始在 $port 端口上监听');
  var receive = <int>[];
  ss.listen((socket) {
    startTime = DateTime.now().microsecondsSinceEpoch;
    print(
        '[Server] ${socket.remoteAddress.address}:${socket.remotePort}[${socket.connectionId}] 已连接');
    socket.listen((data) {
      receive.addAll(data);
    }, onDone: () async {
      var endTime = DateTime.now().microsecondsSinceEpoch;
      var spendTime = (endTime - startTime) / 1000000;
      var result = utf8.decode(receive);
      var totalSize = receive.length / 1024;
      receive.clear();
      print(result);
      await ss.close();
      print(
          '[Server] 远程 ${socket.remoteAddress.address}:${socket.remotePort}[${socket.connectionId}] 已关闭,所以也关闭服务器');
      print(
          '[Server] 服务器已关闭。接收了 $totalSize kb 数据,速度为 ${(totalSize / spendTime).toStringAsFixed(3)} kb/s');
    });
  });

  var pool = UTPSocketClient();
  var s1 = await pool.connect(InternetAddress.tryParse('127.0.0.1')!, port!);
  var cbys = utf8.encode(chinese).length;
  print(
      '[Client] 成功连接到 ${s1?.remoteAddress.address}:${s1?.remotePort}[${s1?.connectionId}]。开始发送 ${(total * cbys) / 1024}kb 数据');
  for (var i = 0; i < total; i++) {
    s1?.write(chinese);
  }
  await s1?.close();
  print('[Client] 客户端已关闭');
  await pool.close();
}

更多关于Flutter网络通信插件utp_protocol的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter网络通信插件utp_protocol的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用utp_protocol插件来进行UTP(Micro Transport Protocol)网络通信的示例。请注意,由于utp_protocol并非一个广泛认知的Flutter插件,以下代码将假设有一个名为utp_protocol的Flutter插件,并基于通常的插件使用方式来进行示例。如果实际插件的API有所不同,请查阅相关文档进行调整。

首先,确保在你的pubspec.yaml文件中添加了utp_protocol插件依赖:

dependencies:
  flutter:
    sdk: flutter
  utp_protocol: ^x.y.z  # 替换为实际版本号

然后,运行flutter pub get来获取依赖。

接下来,在你的Flutter项目中,你可以按照以下方式使用utp_protocol插件来进行UTP网络通信。

示例代码

import 'package:flutter/material.dart';
import 'package:utp_protocol/utp_protocol.dart';  // 假设插件提供这个导入路径

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'UTP Protocol Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: UtpDemoPage(),
    );
  }
}

class UtpDemoPage extends StatefulWidget {
  @override
  _UtpDemoPageState createState() => _UtpDemoPageState();
}

class _UtpDemoPageState extends State<UtpDemoPage> {
  String status = "Not Connected";
  String receivedData = "";

  @override
  void initState() {
    super.initState();
    initUtpConnection();
  }

  void initUtpConnection() async {
    try {
      // 假设UTPClient是插件提供的一个类
      UTPClient client = UTPClient('example.com', 12345);  // 替换为实际的服务器地址和端口

      // 连接到服务器
      await client.connect();
      setState(() {
        status = "Connected";
      });

      // 监听数据接收事件
      client.onDataReceived.listen((data) {
        setState(() {
          receivedData += String.fromCharCodes(data);
        });
      });

      // 发送数据到服务器
      String message = "Hello, UTP!";
      client.send(message.codeUnits);

    } catch (e) {
      print("Error connecting: $e");
      setState(() {
        status = "Error: $e";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('UTP Protocol Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text('Status: $status'),
            SizedBox(height: 16),
            Text('Received Data:', style: TextStyle(fontWeight: FontWeight.bold)),
            Text(receivedData),
          ],
        ),
      ),
    );
  }
}

注意事项

  1. 插件API:上述代码假设utp_protocol插件提供了一个UTPClient类,并且该类具有connectsend方法和onDataReceived事件监听器。如果实际插件的API不同,请查阅插件的官方文档。

  2. 错误处理:在实际应用中,应该添加更多的错误处理逻辑,比如重连机制、超时处理等。

  3. 安全性:UTP协议不像TCP那样有内置的可靠性和错误检查机制,因此在使用时需要特别注意数据的完整性和可靠性。

  4. 平台支持:确保utp_protocol插件支持你的目标平台(如iOS、Android等)。

  5. 依赖管理:确保pubspec.yaml中的依赖版本是最新的,并且与你的Flutter SDK版本兼容。

由于utp_protocol可能是一个假想的插件名称,如果在实际项目中找不到对应的插件,你可能需要寻找或自己实现一个支持UTP协议的Flutter插件。

回到顶部