Flutter以太网通信插件l2ethernet的使用

Flutter以太网通信插件l2ethernet的使用

插件介绍

这个小Dart包允许发送原始的以太网帧。我的用例是向一个名为Colorlight 5A接收卡发送数据,它期望接收到以太网帧,但我在Dart中找不到实现该功能的方法。误导性命名的RawSocket类实际上使用了TCP。

因此,这个包诞生了:通过FFI(C互操作),它使用Linux的socket()接口来发送原始以太网帧。可以用来发送任意以太网数据包,如WOL数据包、ARP欺骗、自定义协议等。

测试

测试包含两部分:一部分可以在非root用户下运行,另一部分需要root权限(或其他类似权限)因为它实际打开了一个原始套接字。我使用tcpdump在后台捕获发送的以太网数据包,并验证其是否符合预期。

编译共享库

这其实很简单,因为C层非常短。我添加了一个buildme.sh脚本。它非常简单。

macOS, Windows, Android, iOS

对不起,这些平台不在我支持范围内。

限制

  • 目前不支持接收帧。
  • 这不是性能优化的:单个帧同步发送出去。如果需要性能,应该使用sendmmsg()。
  • 只支持Linux,并且共享库仅适用于x86_64和aarch64。编译这个库非常简单(参见buildme.sh)。

关于libeth.so的说明

当Dart编译为exe或AOT时,它不会查看packages,因此无法找到libeth.so。虽然将它静态链接到可执行文件或AOT文件中会很好,但在Dart 2.16.1版本中这并不工作。解决方法是将所需的libeth.so文件放在./lib/$march/libeth.so中,其中.是二进制文件的路径(例如sendframe.exe)。

示例代码

示例代码介绍

我添加了两个示例:

  • send_packet.dart:展示如何发送一个简单的原始以太网帧。使用tcpdump -i $nic 'ether proto 0xbeef'可以看到它被发送出去。
  • colorlight.dart:发送几个帧用于Colorlight卡。用于测试此包。

注意事项

  1. 两个示例都需要设置环境变量nic,包含要使用的网络接口名称。
  2. 两个示例都需要以root身份运行,或者二进制文件需要具备使用原始套接字的权限:
    setcap 'cap_net_admin,cap_net_raw+ep' BINARY
    
  3. 由于需要以root身份运行,我强烈建议编译独立的可执行文件(通过dart compile exe),这样可以给它们添加上述权限。这避免了需要以root身份运行dart。

完整示例Demo

send_packet.dart

import 'package:l2ethernet/l2ethernet.dart';

void main() {
  // 设置网络接口名称
  final String nic = Platform.environment['nic'];

  if (nic == null) {
    print('Please set the "nic" environment variable.');
    return;
  }

  // 创建以太网帧
  final EthernetFrame frame = EthernetFrame(
    destination: MacAddress.fromHex('ff:ff:ff:ff:ff:ff'), // 广播地址
    source: MacAddress.fromHex('00:11:22:33:44:55'), // 源MAC地址
    etherType: 0xbeef, // 自定义以太网类型
    payload: Uint8List.fromList([1, 2, 3, 4]), // 载荷
  );

  // 发送以太网帧
  final L2Ethernet l2Ethernet = L2Ethernet(nic);
  l2Ethernet.send(frame);

  print('Sent Ethernet frame!');
}

colorlight.dart

import 'package:l2ethernet/l2ethernet.dart';

void main() {
  // 设置网络接口名称
  final String nic = Platform.environment['nic'];

  if (nic == null) {
    print('Please set the "nic" environment variable.');
    return;
  }

  // 创建以太网帧
  final EthernetFrame frame = EthernetFrame(
    destination: MacAddress.fromHex('ff:ff:ff:ff:ff:ff'), // 广播地址
    source: MacAddress.fromHex('00:11:22:33:44:55'), // 源MAC地址
    etherType: 0xbeef, // 自定义以太网类型
    payload: Uint8List.fromList([1, 2, 3, 4]), // 载荷
  );

  // 发送多个以太网帧
  final L2Ethernet l2Ethernet = L2Ethernet(nic);
  for (int i = 0; i < 5; i++) {
    l2Ethernet.send(frame);
    print('Sent Ethernet frame $i!');
  }
}

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

1 回复

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


l2ethernet 是一个用于在 Flutter 应用中进行以太网通信的插件。它允许应用直接在低层级(L2,数据链路层)与以太网设备进行通信。以下是使用 l2ethernet 插件的基本步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 l2ethernet 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  l2ethernet: ^0.0.1 # 请使用最新版本

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

2. 导入包

在你的 Dart 文件中导入 l2ethernet 包:

import 'package:l2ethernet/l2ethernet.dart';

3. 初始化以太网连接

使用 L2Ethernet 类来初始化和配置以太网连接。以下是一个简单的示例:

void main() async {
  // 初始化 L2Ethernet
  L2Ethernet l2Ethernet = L2Ethernet();

  // 打开以太网接口
  bool isOpened = await l2Ethernet.open("eth0"); // eth0 是以太网接口名称
  if (isOpened) {
    print("以太网接口打开成功");

    // 发送数据
    List<int> data = [0x01, 0x02, 0x03, 0x04];
    await l2Ethernet.send(data);
    print("数据发送成功");

    // 接收数据
    List<int> receivedData = await l2Ethernet.receive();
    print("接收到的数据: $receivedData");

    // 关闭以太网接口
    await l2Ethernet.close();
    print("以太网接口已关闭");
  } else {
    print("无法打开以太网接口");
  }
}

4. 处理接收数据

receive 方法返回一个 List<int>,表示接收到的字节数据。你可以根据需要进行解析和处理。

5. 关闭连接

使用 close 方法来关闭以太网接口,以释放资源。

6. 权限与配置

在某些平台上(如 Android),使用以太网功能可能需要特定的权限和配置。确保你在 AndroidManifest.xml 文件中添加了必要的权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
回到顶部