在Dart中写入/读取到/从套接字数据的字节数 [英] writing/reading number of bytes to/from socket data in Dart

查看:2551
本文介绍了在Dart中写入/读取到/从套接字数据的字节数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的服务器/客户端套接字代码中,服务器尝试从0到1023发送int。客户端接收正确数目的int,但它们在255处。为什么是这样的,什么是正确的方式?

In the following server/client socket code, the server tries to send ints from 0 to 1023. The client receives the right number of ints but they wrap at 255. Why is this and what is the proper way?

import 'dart:async';
import 'dart:io';

main() async {
  final server = await ServerSocket.bind('127.0.0.1', 4041);
  server.listen((Socket socket) {
    print('Got connected ${socket.remoteAddress}');
    for(int i=0; i<1024; i++) {
      socket.add([i]);
    }
    socket.close();
    print('Closed ${socket.remoteAddress}');
  });
}



* Client *



* Client *

import 'dart:async';
import 'dart:io';

main() async {
  final client = await Socket.connect('127.0.0.1', 4041);
  client.listen(
      (var data) => print('Got $data'),
      onDone: () { print('Done'); client.close(); },
      onError: (e) { print('Got error $e'); client.close(); });
  print('main done');
}

此外,感觉像Socket api有点不同 - 更多Dartish比其他语言的支持读取它作为流。但是,如果你只想读取 N 字节怎么办?你如何实现呢?我看到 take 方法( Stream take(int count)),但我不清楚计数读取了多少字节。因为Socket实现了流<列表< int>> 并且因为int不是一个固定大小的实体(我想??),你怎么知道已经读了多少字节?

Also, it feels like the Socket api is a bit different - being more Dartish than other languages the way it supports reading as a stream. But what if you just want to read N bytes? How do you achieve that? I see the take method (Stream take(int count)) but I'm not clear on what exactly count is taking, especially in terms of how many bytes have been read. Because Socket implements Stream< List < int > > and because int is not really a fixed size entity (I think??), how do you know how many bytes have been read?

推荐答案

这对我有用,我不确定这是最优雅的解决方案

This worked for me, I'm not sure this is the most elegant solution

import 'dart:io';
import 'dart:async';
import 'dart:typed_data';

main() async {
  final server = await ServerSocket.bind('127.0.0.1', 4041);
  server.listen((Socket socket) {
    print('Got connected ${socket.remoteAddress}');

    var toByte = new StreamTransformer<List<int>, Uint8List>.fromHandlers(
        handleData: (data, sink) {
      sink.add(new Uint64List.fromList(data).buffer.asUint8List());
    });

    var streamController = new StreamController<List<int>>();
    streamController.stream.transform(toByte).pipe(socket);

    for (int i = 0; i < 1024; i++) {
      streamController.add([i]);
    }
    streamController.close();
    print('Closed ${socket.remoteAddress}');
  });
}





import 'dart:io';
import 'dart:async';

main() async {
  final Socket client = await Socket.connect('127.0.0.1', 4041);

  var fromByte = new StreamTransformer<List<int>, List<int>>.fromHandlers(
      handleData: (data, sink) {
    sink.add(data.buffer.asInt64List());
  });

  client.transform(fromByte).listen((e) => e.forEach(print));
  print('main done');
}

原始尝试次数:
$ b

Original attempt:

import 'dart:io';
import 'dart:typed_data';

main() async {
  final server = await ServerSocket.bind('127.0.0.1', 4041);
  server.listen((Socket socket) {
    print('Got connected ${socket.remoteAddress}');
    for(int i=0; i<1024; i++) {
      socket.add(new Uint64List.fromList([i]).buffer.asUint8List());
    }
    socket.close();
    print('Closed ${socket.remoteAddress}');
  });
}





import 'dart:io';
import 'dart:typed_data';

main() async {
  final Socket client = await Socket.connect('127.0.0.1', 4041);
  client.listen(
      (var data) {
        var ints = new Uint8List.fromList(data).buffer.asInt64List();
        ints.forEach((i) => print('Got $i'));
      },
      onDone: () { print('Done'); client.close(); },
      onError: (e) { print('Got error $e'); client.close(); });
  print('main done');
}

如果你不需要Int64的范围,你也可以使用Int32 ,Int16或某些UIntXX类型或任何符合你的值范围最好,保存一些冗余传输的0字节。

If you don't need the range of an Int64 you can also use Int32, Int16 or some of the UIntXX types or whatever fits your value range best, to save some redundantly transmitted 0-bytes.

我怀疑使用一个转换器在此解释 https://www.dartlang.org/articles/converters-and-codecs/ 可以用来做得更优雅。这似乎与 https://gist.github.com/xxgreg/9104926 相似,但我不得不承认我无法将这些示例应用于您的用例。

I have the suspicion that using a converter like it's explained here https://www.dartlang.org/articles/converters-and-codecs/ could be used to do it more elegantly. This seems similar https://gist.github.com/xxgreg/9104926 but I have to admit that I'm not able to apply these examples for your use case.

更新

我的工作方式如同上面链接的文章所示

I got it working like shown in the articles linked above

import 'dart:convert';
import 'dart:typed_data';

class IntConverter extends Converter<List<int>, List<int>> {
  const IntConverter();

  List<int> convert(List<int> data) {
    if (data is Uint8List) {
      return data.buffer.asInt64List();
    } else {
      return new Uint64List.fromList(data).buffer.asUint8List();
    }
  }

  IntSink startChunkedConversion(sink) {
    return new IntSink(sink);
  }
}

class IntSink extends ChunkedConversionSink<List<int>> {
  final _converter;
  // fales when this type is used
  // final ChunkedConversionSink<List<int>> _outSink;
  final _outSink;

  IntSink(this._outSink) : _converter = new IntConverter();

  void add(List<int> data) {
    _outSink.add(_converter.convert(data));
  }

  void close() {
    _outSink.close();
  }
}





import 'dart:io';
import 'dart:typed_data';

main() async {
  final server = await ServerSocket.bind('127.0.0.1', 4041);
  server.listen((Socket socket) {
    print('Got connected ${socket.remoteAddress}');

    for (int i = 0; i < 1024; i++) {
      socket.add(new Uint64List.fromList([i]).buffer.asUint8List());
    }
    socket.close();
    print('Closed ${socket.remoteAddress}');
  });
}





import 'dart:io';
import 'byte_converter.dart';

main() async {
  final Socket client = await Socket.connect('127.0.0.1', 4041);
  client.transform(new IntConverter()).listen((e) => e.forEach(print));
  print('main done');
}

这篇关于在Dart中写入/读取到/从套接字数据的字节数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆