【问题标题】:How to manage multiple data from a StreamSubscription in dart?如何在 dart 中管理来自 StreamSubscription 的多个数据?
【发布时间】:2021-11-17 22:56:48
【问题描述】:

我想从客户端应用发送和检索多个数据。

我试着这样做:

(服务器代码)

void start() async{
  try{
    _server = await ServerSocket.bind('127.0.0.1', 1234);
    print('Waiting for connections');
    _server.listen(_handleClient);
  } catch(e) { await _server.close(); }
}

void _handleClient(Socket socket) async {
  late String request, username, password;
  socket.listen((data) => request = String.fromCharCodes(data));
  socket.write(_publicKey);
  socket.listen((data) => _clientPublicKey = _decrypt(String.fromCharCodes(data))); 
  socket.listen((data) => username = _decrypt(String.fromCharCodes(data)));
  socket.listen((data) => password = _decrypt(String.fromCharCodes(data)));

  var database = Database(username, password);

  switch (request) {
    case 'getItem':
      getItem(socket, database);
      break;
    case 'addItem':
      addItem(socket, database);
      break;
      [...]
  }
}

但我有这个例外:

Waiting for connections
Unhandled exception:
Bad state: Stream has already been listened to.
#0      _StreamController._subscribe (dart:async/stream_controller.dart:635:7)
#1      _ControllerStream._createSubscription (dart:async/stream_controller.dart:786:19)
#2      _StreamImpl.listen (dart:async/stream_impl.dart:473:9)
#3      _Socket.listen (dart:io-patch/socket_patch.dart:2026:31)
#4      Server._handleClient (file:///D:/MyApps/Dart/my_netia_server/bin/Network/Server.dart:65:12)
#5      _RootZone.runUnaryGuarded (dart:async/zone.dart:1620:10)
#6      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#7      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
[14 more...]

Process finished with exit code 255

担心的是每次接收到数据时都会调用listen中定义的函数。 我想要的是我的代码仅在必要时才需要数据。这将使我能够更简单地准确管理接收到的数据类型(例如:Object、String、int、...)

【问题讨论】:

    标签: sockets dart networking stream


    【解决方案1】:

    如果您想逐个访问流的独立事件,并且当您准备好时,我推荐 package:async 中的 StreamQueue 类。

    您也可以使用dart:async 平台库中的StreamIterator 类,但StreamQueue 有一个大大改进的API。

    使用示例:

    void _handleClient(Socket socket) async {
      var queue = StreamQueue(socket);
      
      String request = String.fromCharCodes(await queue.next);
      socket.write(_publicKey);
      _clientPublicKey = 
          _decrypt(String.fromCharCodes(await queue.next)));
      String username = 
          _decrypt(String.fromCharCodes(await queue.next)));
      String password = 
          _decrypt(String.fromCharCodes(await queue.next)));
      ...
    

    这确实假设各个响应部分作为独立事件出现。这就是原版所做的,但这不是我所依赖的。

    您更有可能希望累积字节直到有足够的字节,然后解析其中的初始部分。

    【讨论】:

    • 您的回答对我来说很完美,非常感谢! (我只是将 queue.next() 更改为 queue.next 并删除了不必要的 ')')我现在唯一的问题是,当我一个接一个地发送几个 'write' 时,它们会堆叠在一起。我发现的一种解决方案是通过一直循环 write-listen 来“等待”服务器来同步服务器和客户端。可能有更好的解决方案,但我认为这需要另一个问题。
    • 我的错,靠记忆工作。我会修复代码。
    猜你喜欢
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 2022-06-10
    • 2014-04-27
    • 1970-01-01
    • 2021-07-29
    相关资源
    最近更新 更多