ZetCode

Dart RawSocketEvent

最后修改于 2025 年 4 月 4 日

Dart 中的 RawSocketEvent 类代表原始套接字连接上发生的事件。它与 RawSocket 一起用于低级网络通信。

RawSocketEvent 提供了读取、写入、关闭和错误状态的事件类型。它是 Dart dart:io 库的一部分,用于非 Web 应用程序。

基本定义

RawSocketEvent 是一个枚举类,用于定义套接字事件。这些事件在套接字操作期间触发,并且必须进行处理。

关键事件包括 READ(用于传入数据)、WRITE(用于输出就绪)和 CLOSED(用于连接终止)。错误情况也会被报告。

基本的 Socket 事件处理

此示例展示了使用 RawSocketEvent 进行基本的事件处理。

main.dart
import 'dart:io';

void main() async {
  var socket = await RawSocket.connect('example.com', 80);
  
  socket.listen((event) {
    switch (event) {
      case RawSocketEvent.read:
        print('Data available to read');
        break;
      case RawSocketEvent.write:
        print('Ready to send data');
        break;
      case RawSocketEvent.closed:
        print('Connection closed');
        break;
    }
  });
  
  socket.writeEventsEnabled = true;
}

我们连接到服务器并监听套接字事件。listen 回调接收 RawSocketEvent 值,指示套接字状态的变化。

$ dart main.dart
Ready to send data
Data available to read
Connection closed

在 READ 事件上读取数据

此示例演示了在发生 READ 事件时读取数据。

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

void main() async {
  var socket = await RawSocket.connect('example.com', 80);
  var request = 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n';
  
  socket.write(request.codeUnits);
  
  socket.listen((event) {
    if (event == RawSocketEvent.read) {
      var data = socket.read();
      if (data != null) {
        print(utf8.decode(data));
      }
    } else if (event == RawSocketEvent.closed) {
      socket.close();
    }
  });
}

我们发送一个 HTTP 请求,并在发生 READ 事件时读取响应。socket.read() 方法将可用数据作为字节列表返回。

$ dart main.dart
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
...

处理 Write 事件

此示例展示了如何处理 WRITE 事件以进行高效的数据发送。

main.dart
import 'dart:io';

void main() async {
  var socket = await RawSocket.connect('localhost', 8080);
  var messages = ['Hello', 'World', 'From', 'Dart'];
  var index = 0;
  
  socket.listen((event) {
    if (event == RawSocketEvent.write && index < messages.length) {
      socket.write(messages[index++].codeUnits);
      print('Sent: ${messages[index-1]}');
    }
    
    if (index == messages.length) {
      socket.shutdown(SocketDirection.send);
    }
  });
  
  socket.writeEventsEnabled = true;
}

我们仅在套接字准备好写入时才发送消息。WRITE 事件指示套接字何时可以接受更多数据而不阻塞。

$ dart main.dart
Sent: Hello
Sent: World
Sent: From
Sent: Dart

错误事件处理

此示例演示了处理套接字上的错误事件。

main.dart
import 'dart:io';

void main() async {
  try {
    var socket = await RawSocket.connect('invalid.host', 80);
    
    socket.listen((event) {
      if (event == RawSocketEvent.read) {
        print('Data received');
      } else if (event == RawSocketEvent.closed) {
        print('Connection closed');
      } else if (event == RawSocketEvent.readError ||
                 event == RawSocketEvent.writeError) {
        print('Error occurred on socket');
        socket.close();
      }
    });
  } on SocketException catch (e) {
    print('Connection failed: ${e.message}');
  }
}

我们处理连接错误和运行时套接字错误。错误事件指示套接字连接或操作存在问题。

$ dart main.dart
Connection failed: Failed host lookup: 'invalid.host'

完整的 Socket 客户端

此示例展示了一个具有所有事件类型的完整套接字客户端。

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

void main() async {
  try {
    var socket = await RawSocket.connect('example.com', 80);
    var request = 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n';
    
    socket.listen((event) {
      switch (event) {
        case RawSocketEvent.read:
          var data = socket.read();
          if (data != null) {
            print(utf8.decode(data.take(100)));
          }
          break;
        case RawSocketEvent.write:
          socket.write(request.codeUnits);
          socket.writeEventsEnabled = false;
          break;
        case RawSocketEvent.closed:
          print('Connection closed by server');
          socket.close();
          break;
        case RawSocketEvent.readError:
        case RawSocketEvent.writeError:
          print('Socket error occurred');
          socket.close();
          break;
      }
    });
    
    socket.writeEventsEnabled = true;
  } on SocketException catch (e) {
    print('Connection error: ${e.message}');
  }
}

此完整示例处理所有套接字事件:初始写入、读取响应数据以及在关闭或错误时进行适当的清理。

$ dart main.dart
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1256
...
Connection closed by server

最佳实践

来源

Dart RawSocketEvent 文档

本教程涵盖了 Dart 的 RawSocketEvent 类,并通过实际示例展示了套接字编程的事件处理、数据传输和错误管理。

作者

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

列出 所有 Dart 教程