Skip to content

Instantly share code, notes, and snippets.

@PlugFox
Last active May 4, 2024 08:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save PlugFox/9cc2adb1d8df24fae2164e95dba6a911 to your computer and use it in GitHub Desktop.
Save PlugFox/9cc2adb1d8df24fae2164e95dba6a911 to your computer and use it in GitHub Desktop.
Пример обмена данными между клиентом и сервером по протоколу TCP/IP
/*
* Пример обмена данными между клиентом и сервером по протоколу 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