WebSockets — это технология для real-time双向 связи между клиентом и сервером. В этой статье реализуем WebSocket клиент во Flutter с нуля.
Что такое WebSockets?
WebSocket — это протокол, который предоставляет:
- Постоянное соединение
- Двустороннюю связь в реальном времени
- Низкие накладные расходы
- Поддержка на всех платформах
Установка
dependencies:
web_socket_channel: ^2.4.0
Базовая реализация
import 'package:web_socket_channel/web_socket_channel.dart';
class WebSocketService {
final WebSocketChannel _channel;
final StreamController<String> _messages = StreamController.broadcast();
WebSocketService(String url)
: _channel = WebSocketChannel.connect(url);
Stream<String> get messages => _messages.stream;
void send(String message) {
_channel.sink.add(message);
}
void dispose() {
_channel.sink.close();
_messages.close();
}
}
Обработка сообщений
class MyWebSocketWidget extends StatefulWidget {
@override
Widget build(BuildContext context) {
final ws = WebSocketService('ws://example.com');
return StreamBuilder<String>(
stream: ws.messages,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text('Received: ${snapshot.data}');
}
return CircularProgressIndicator();
},
);
}
}
Reconnection
class ReconnectingWebSocket {
final String url;
WebSocketChannel? _channel;
Timer? _reconnectTimer;
int _retryCount = 0;
static const _maxRetries = 5;
static const _baseDelay = Duration(seconds: 1);
void connect() {
_channel = WebSocketChannel.connect(url);
_channel!.stream.listen(
(data) {
_retryCount = 0; // Сбросить счётчик
// Обработка данных
},
onError: (error) {
print('WebSocket error: $error');
_scheduleReconnect();
},
onDone: () {
print('WebSocket closed');
_scheduleReconnect();
},
);
}
void _scheduleReconnect() {
_reconnectTimer?.cancel();
final delay = _baseDelay * pow(2, _retryCount).toInt();
_reconnectTimer = Timer(delay, () {
if (_retryCount < _maxRetries) {
_retryCount++;
connect();
}
});
}
void disconnect() {
_reconnectTimer?.cancel();
_channel?.sink.close();
}
}
Heartbeat
class HeartbeatWebSocket {
Timer? _heartbeatTimer;
void connect() {
_channel = WebSocketChannel.connect(url);
// Heartbeat каждые 30 секунд
_heartbeatTimer = Timer.periodic(
Duration(seconds: 30),
(_) => _channel?.sink.add('ping'),
);
}
@override
void dispose() {
_heartbeatTimer?.cancel();
super.dispose();
}
}
Заключение
WebSockets — идеальны для чатов, real-time обновлений и онлайн игр. Реализуйте reconnection и heartbeat для production.