sockets - 我需要在客户端套接字应用程序上使用 Dart 的惯用解决方案
问题描述
在 Dart 控制台中测试服务器套接字及其客户端。我发现我必须引入延迟的问题,await Future.delayed(Duration(milliseconds: 1));
以便可以在我通过控制台请求消息的同时执行 sockect 的侦听周期。
我确信 Dart 中有更聪明的解决方案,但我还没有找到方法。
要运行代码,只需将代码复制/粘贴到一个文件中server.dart
并client.dart
运行它们。
这里的客户:
import 'dart:convert' show utf8;
import 'dart:io';
InternetAddress HOST = InternetAddress.loopbackIPv4;
const PORT = 7654;
void main() {
Socket.connect(HOST, PORT).then((socket) async {
print('connected to server $HOST$PORT');
socket.handleError((error) {
print('handleError $error');
});
socket.write('Hello, World from a client!');
socket.cast<List<int>>().transform(utf8.decoder).listen(onData, onDone: () {
print("Done");
}, onError: (error) {
print('onError: $error');
});
while (true) {
await Future.delayed(Duration(milliseconds: 1));
stdout.write("Enter your msg : ");
var msg = stdin.readLineSync();
socket.write(msg);
}
}).catchError((error) {
print('catchError: $error');
});
}
onData(data) {
print('onData: ' + data);
}
这是一个请求发送到服务器的键盘输入的简单循环,这总是有效的,但是如果我删除await Future.delayed ...,我不会收到来自服务器的响应。
我对这种方法作为解决方案不太满意。是否有替代方案,可能是孤立的、精心打造的未来或溪流?
这里是服务器:
import 'dart:io';
import 'dart:convert' show utf8;
InternetAddress HOST = InternetAddress.loopbackIPv4;
const PORT = 7654;
void main() {
ServerSocket.bind(HOST, PORT).then((ServerSocket srv) {
print('serversocket is ready');
srv.listen(handleClient);
}).catchError(print);
}
void handleClient(Socket client) {
var client_id =
'${client.hashCode} => ${client.remoteAddress.address}:${client.remotePort}';
print('Connection from: $client_id');
client.write("Hello from Simple Socket Server!\n");
// data from client:
client.cast<List<int>>().transform(utf8.decoder).listen((msg) {
print('${client.hashCode}: $msg');
// Here switch msg
client.write('Reply: ' + msg);
//client.close();
});
}
解决方案
你有一个同步循环:while (true) { ... readLineSync() ... }
. 整个循环是同步的,这意味着在循环结束之前不会运行其他代码(如果有条件true
,则永远不会)。您必须在该同步循环期间放弃控制,以允许其他异步代码也运行。
因此,如果您可以将readLine
线路更改为var msg = await stdin.readLine();
,那么您在等待输入时不会阻止任何人。可悲的是你不能,没有 asynchronous readLine
。因此,另一种方法是LineSplitter
在 stdin 上使用 a 来异步获取行:
var stdinLines = ;
...
stdout.write("Enter your msg : ");
await for (var msg in stdin.transform(utf8.decoder).transform(const LineSplitter())) {
socket.write(msg);
stdout.write("Enter your msg : ");
}
推荐阅读
- laravel - Laravel Route:dispatch 使用 EncryptCookie 创建新会话
- python - 在 python 中向第三方类添加属性的建议方法
- r - 用于诊断的正则表达式
- html - 如何在将动态表导出到另一个文件时在 html 中呈现动态表
- r - 用于将每个非空单元格的 data.table 转换为长格式的矢量化解决方案,以列+行索引作为参考
- html - 用 CSS 中的一句话剪辑视频
- java - “未使用@Test 注释或未包含”,我已尽力找到解决此问题的方法,但没有结果
- excel - VBA - 如果不满足其他子中的条件,如何退出主子
- javascript - 无法在从 React/redux 中的另一个 js 文件导入的 App.js 中加载函数
- textbox - 如何在 dm-script 中动态使用对话框文本框