ZetCode

Dart SocketControlMessage

最后修改于 2025 年 4 月 4 日

Dart 中的 SocketControlMessage 类代表与套接字一起使用的网络控制消息。这些消息携带协议特定的信息。

控制消息通常用于高级套接字操作,例如访问数据包头部或设置套接字选项。它们是 Dart dart:io 库的一部分,用于低级网络编程。

基本定义

SocketControlMessage 是一个抽象类,代表特定于平台的控制消息。它与 RawDatagramSocket 和 RawSocket 一起使用。

主要功能包括协议特定的数据访问和平台独立性。实际实现因操作系统和协议而异。

基本的 SocketControlMessage 用法

此示例演示如何从数据报套接字接收控制消息。

main.dart
import 'dart:io';
import 'dart:typed_data';

void main() async {
  final socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
  
  socket.listen((event) {
    if (event == RawSocketEvent.read) {
      final datagram = socket.receive();
      final controlMessages = socket.receiveControlMessages();
      
      if (controlMessages != null) {
        for (final message in controlMessages) {
          print('Received control message: ${message.runtimeType}');
        }
      }
    }
  });
  
  // Send a test packet to ourselves
  socket.send(Uint8List.fromList([1, 2, 3]), 
      InternetAddress.loopbackIPv4, socket.port);
}

我们创建一个数据报套接字并监听带有控制消息的传入数据包。receiveControlMessages() 方法返回任何控制消息。

$ dart main.dart
Received control message: _RawSocketControlMessage

处理 IP_TTL 控制消息

此示例演示了处理 IP 生存时间 (TTL) 控制消息。

main.dart
import 'dart:io';
import 'dart:typed_data';

void main() async {
  final socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
  
  // Enable receiving TTL information
  socket.setOption(SocketOption.ipReceiveTTL, true);
  
  socket.listen((event) {
    if (event == RawSocketEvent.read) {
      final datagram = socket.receive();
      final controlMessages = socket.receiveControlMessages();
      
      if (controlMessages != null) {
        for (final message in controlMessages) {
          if (message.level == SocketOption.ipLevel &&
              message.type == SocketOption.ipTTL) {
            print('Packet TTL: ${message.data[0]}');
          }
        }
      }
    }
  });
  
  // Send test packet
  socket.send(Uint8List.fromList([1, 2, 3]), 
      InternetAddress.loopbackIPv4, socket.port);
}

我们配置套接字以接收 TTL 信息,然后从控制消息中提取它。消息包含协议级别和类型信息。

$ dart main.dart
Packet TTL: 64

发送控制消息

此示例展示了如何发送附加了控制消息的数据包。

main.dart
import 'dart:io';
import 'dart:typed_data';

void main() async {
  final receiver = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
  final sender = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
  
  // Enable TTL control messages on receiver
  receiver.setOption(SocketOption.ipReceiveTTL, true);
  
  receiver.listen((event) {
    if (event == RawSocketEvent.read) {
      final datagram = receiver.receive();
      final controlMessages = receiver.receiveControlMessages();
      
      if (controlMessages != null) {
        for (final message in controlMessages) {
          print('Received TTL: ${message.data[0]}');
        }
      }
    }
  });
  
  // Create control message to set TTL
  final ttlMessage = RawSocketControlMessage.fromHandled(
    SocketOption.ipLevel,
    SocketOption.ipTTL,
    Uint8List.fromList([1]) // Set TTL to 1
  );
  
  // Send with control message
  sender.send(
    Uint8List.fromList([1, 2, 3]),
    InternetAddress.loopbackIPv4,
    receiver.port,
    controlMessages: [ttlMessage]
  );
}

我们创建一个控制消息来设置 TTL 值,并将其附加到传出的数据包。接收者将在其控制消息中看到此 TTL 值。

$ dart main.dart
Received TTL: 1

处理多个控制消息

此示例演示了处理不同类型的控制消息。

main.dart
import 'dart:io';
import 'dart:typed_data';

void main() async {
  final socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
  
  // Enable multiple control message types
  socket.setOption(SocketOption.ipReceiveTTL, true);
  socket.setOption(SocketOption.ipReceiveTOS, true);
  
  socket.listen((event) {
    if (event == RawSocketEvent.read) {
      final datagram = socket.receive();
      final controlMessages = socket.receiveControlMessages();
      
      if (controlMessages != null) {
        for (final message in controlMessages) {
          if (message.level == SocketOption.ipLevel) {
            if (message.type == SocketOption.ipTTL) {
              print('TTL: ${message.data[0]}');
            } else if (message.type == SocketOption.ipTOS) {
              print('TOS: ${message.data[0]}');
            }
          }
        }
      }
    }
  });
  
  // Send test packet
  socket.send(Uint8List.fromList([1, 2, 3]), 
      InternetAddress.loopbackIPv4, socket.port);
}

我们配置套接字以接收 TTL 和 TOS(服务类型)控制消息。代码区分了不同的消息类型。

$ dart main.dart
TTL: 64
TOS: 0

特定于平台的控制消息

此示例展示了特定于平台的控制消息处理。

main.dart
import 'dart:io';
import 'dart:typed_data';

void main() async {
  final socket = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
  
  // Platform-specific options
  if (Platform.isLinux) {
    socket.setOption(SocketOption.ipPacketInfo, true);
  } else if (Platform.isMacOS) {
    socket.setOption(SocketOption.ipRecvDstAddr, true);
  }
  
  socket.listen((event) {
    if (event == RawSocketEvent.read) {
      final datagram = socket.receive();
      final controlMessages = socket.receiveControlMessages();
      
      if (controlMessages != null) {
        print('Received ${controlMessages.length} control messages');
        
        for (final message in controlMessages) {
          print('Message level: ${message.level}, type: ${message.type}');
          print('Data length: ${message.data.length} bytes');
        }
      }
    }
  });
  
  // Send test packet
  socket.send(Uint8List.fromList([1, 2, 3]), 
      InternetAddress.loopbackIPv4, socket.port);
}

我们演示了特定于平台的控制消息选项。实际可用的选项和消息格式因操作系统而异。

$ dart main.dart
Received 1 control messages
Message level: 0, type: 8
Data length: 12 bytes

最佳实践

来源

Dart SocketControlMessage 文档

本教程通过实际示例介绍了 Dart 的 SocketControlMessage 类,展示了控制消息的接收、发送和特定于平台的处理。

作者

我叫 Jan Bodnar,我是一位充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在教学编程方面有十多年的经验。

列出 所有 Dart 教程