Last active
May 4, 2024 08:45
-
-
Save PlugFox/9cc2adb1d8df24fae2164e95dba6a911 to your computer and use it in GitHub Desktop.
Пример обмена данными между клиентом и сервером по протоколу TCP/IP
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Пример обмена данными между клиентом и сервером по протоколу TCP/IP | |
* https://gist.github.com/PlugFox/9cc2adb1d8df24fae2164e95dba6a911 | |
* https://dartpad.dev?id=9cc2adb1d8df24fae2164e95dba6a911 | |
* Matiunin Mikhail <plugfox@gmail.com>, 29 October 2023 | |
*/ | |
// ignore_for_file: avoid_print, lines_longer_than_80_chars | |
import 'dart:async'; | |
import 'dart:convert'; | |
import 'dart:io'; | |
/// Преобразователь JSON-данных в байтовый поток и обратно | |
typedef JsonMap = Map<String, Object?>; | |
final codec = ( | |
encoder: JsonUtf8Encoder(), | |
decoder: | |
const Utf8Decoder().fuse(const JsonDecoder()).cast<Object?, JsonMap>(), | |
); | |
/// Запускает сервер и возвращает функцию, которая закроет сервер | |
Future<Future<void> Function()> server( | |
InternetAddress address, int port) async { | |
// Создаем сервер на указанном адресе и порту | |
final server = await ServerSocket.bind(address, port); | |
print('Server started on ${server.address.address}:${server.port}'); | |
// Ожидаем новых соединений | |
final sub = server.listen( | |
(client) { | |
print('Client connected: ' | |
'${client.remoteAddress.address}:${client.remotePort}'); | |
// При получении данных от клиента | |
client.listen((bytes) { | |
// Обрабатываем запрос | |
final request = codec.decoder.convert(bytes); | |
final <String, Object?>{'id': id, 'message': message} = request; | |
print('> $message'); | |
// Отправляем ответ клиенту | |
final responseBytes = codec.encoder.convert(<String, Object?>{ | |
'id': id, | |
'message': 'Hello, Client #$id! I am Server.', | |
}); | |
client.add(responseBytes); | |
}, onDone: () { | |
print('Client disconnected: ' | |
'${client.remoteAddress.address}:${client.remotePort}'); | |
client.close(); | |
}); | |
}, | |
cancelOnError: false, | |
); | |
/// Возвращаем функцию, которая закроет сервер и все соединения | |
return () async { | |
await sub.cancel(); | |
await server.close(); | |
print('Server closed'); | |
}; | |
} | |
/// Создает клиента, который отправляет сообщение серверу и выводит ответ | |
Future<void> client(int id) async { | |
// Создаем соединение с сервером на адресе 127.0.0.1 (localhost) и порту 8080 | |
final socket = await Socket.connect('127.0.0.1', 8080); | |
// Отправляем сообщение серверу | |
final requestBytes = codec.encoder.convert(<String, Object?>{ | |
'id': id, | |
'message': 'Hello, Server! I am Client #$id', | |
}); | |
socket.add(requestBytes); | |
// Ожидаем ответ от сервера и выводим его | |
final completer = Completer<JsonMap>(); | |
final sub = socket.map(codec.decoder.convert).listen(completer.complete); | |
final response = await completer.future; | |
print('< ${response['message']}'); | |
// Закрыть соединение после завершения обмена данными | |
await sub.cancel(); | |
await socket.close(); | |
socket.destroy(); | |
} | |
/// Точка входа в приложение | |
/// Запускает сервер и 3 клиента | |
/// Закрывает сервер после завершения работы клиентов | |
void main([List<String>? arguments]) => Future<void>(() async { | |
final delimiter = '\n${'-' * 15}\n'; | |
Future<void> sleep() => | |
Future<void>.delayed(const Duration(milliseconds: 250)); | |
// Запускаем сервер на порту 8080 | |
final close = await server(InternetAddress.loopbackIPv4, 8080); | |
print(delimiter); | |
await sleep(); | |
// Запускаем 3 клиента | |
for (var i = 1; i <= 3; i++) { | |
await client(i); | |
await sleep(); | |
print(delimiter); | |
} | |
await sleep(); | |
// Закрываем сервер | |
await close(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment