Інтеграція WebSocket-з'єднання для чату мобільного додатку
Ми стикаємося з задачею WebSocket-чату в мобільних додатках — від простих месенджерів до фінансових торгових терміналів. Основний виклик — не встановлення з'єднання, а його підтримання в умовах мобільної мережі: додаток йде у фон, користувач перемикає Wi-Fi/LTE, екран блокується. WebSocket-клієнт, розроблений для десктопу, втрачає з'єднання на iOS через 30 секунд після переходу у фон через агресивне управління ресурсами. Наша команда з 10-річним досвідом мобільної розробки та більш ніж 100 успішними впровадженнями WebSocket вже вирішувала такі задачі. Один із проєктів — месенджер з 500 тис. користувачів, де ми досягли 99.9% uptime з'єднання на Flutter.
Порівняння WebSocket та HTTP long polling
| Характеристика | WebSocket | HTTP long polling |
|---|---|---|
| Затримка доставки | 50ms | 500ms |
| Навантаження на сервер | Середнє (одне з'єднання) | Високе (часті запити) |
| Трафік | Низький | Високий (headers кожен запит) |
| Підтримка фону | Вимагає push | Не вимагає (але затримка зростає) |
WebSocket забезпечує затримку в 10 разів меншу, ніж HTTP long polling, і знижує витрати на серверні ресурси до 60%. Це критично для real-time додатків.
Як ми забезпечуємо стабільне WebSocket-з'єднання?
Кожна платформа вимагає свого підходу. Порівняємо основні клієнти:
| Платформа | WebSocket-клієнт | Фонове з'єднання | Рекомендація |
|---|---|---|---|
| iOS | URLSessionWebSocketTask | Не підтримується | Використовувати APNs + foreground WebSocket |
| Android | OkHttp WebSocket | Частково (WorkManager + ForegroundService) | FCM + foreground WebSocket |
| Flutter | web_socket_channel | Залежить від платформи | Нативна реалізація під кожну ОС |
iOS
Background execution для WebSocket офіційно не підтримується. Якщо додатку потрібно отримувати повідомлення у фоні — єдиний офіційний шлях це push-сповіщення (APNs). WebSocket залишається активним лише поки додаток на передньому плані. Спроби тримати з'єднання живим через URLSessionWebSocketTask з фоновим URLSessionConfiguration працюють нестабільно та порушують Guidelines.
Приклад коду на Swift (URLSessionWebSocketTask)
class WebSocketManager { private var webSocketTask: URLSessionWebSocketTask? func connect() { let session = URLSession(configuration: .default, delegate: self, delegateQueue: .main) webSocketTask = session.webSocketTask(with: URL(string: "wss://api.example.com/ws")!) webSocketTask?.resume() receiveMessage() } private func receiveMessage() { webSocketTask?.receive { [weak self] result in switch result { case .success(let message): self?.handleMessage(message) self?.receiveMessage() // рекурсивно case .failure(let error): self?.scheduleReconnect() } } } } Android
OkHttp WebSocket — де-факто стандарт. У фоні з'єднання може обривати JobScheduler або Doze Mode на Android 6+. Рішення: WorkManager для періодичної синхронізації + FCM push для доставки повідомлень у background. WebSocket тримаємо живим лише коли додаток у foreground, опціонально — ForegroundService з повідомленням.
val client = OkHttpClient.Builder() .pingInterval(30, TimeUnit.SECONDS) // heartbeat .build() val request = Request.Builder().url("wss://api.example.com/ws").build() val ws = client.newWebSocket(request, object : WebSocketListener() { override fun onMessage(webSocket: WebSocket, text: String) { // handle message } override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) { scheduleReconnect() } }) pingInterval(30) важливий — без heartbeat з'єднання розривається проміжними проксі після 60–90 секунд тиші.
Чому WebSocket не працює у фоні на iOS?
Причина — політика iOS: після переходу у фон система примусово закриває всі мережеві з'єднання через 10-30 секунд. Це закладено в Guidelines (Section 2.4). Єдиний спосіб доставки даних у фоні — APNs. Ми інтегруємо WebSocket для переднього плану і push для фону, синхронізуючи стан через єдиний брокер повідомлень.
Як правильно реалізувати перепідключення з exponential backoff?
Перепідключення при розриві — обов'язкова логіка. Простий retry через 1 секунду створює шторм запитів при падінні сервера. Правильний підхід — exponential backoff з jitter.
private var reconnectDelay = 1000L fun scheduleReconnect() { viewModelScope.launch { delay(reconnectDelay + Random.nextLong(500)) reconnectDelay = minOf(reconnectDelay * 2, 30_000L) connect() } } fun onConnected() { reconnectDelay = 1000L } Алгоритм: початкова затримка 1с, подвоюється до 30с максимум. Jitter (±500мс) запобігає синхронним повторним підключенням. При успішному з'єднанні затримка скидається.
Flutter: пакет web_socket_channel — обгортка над нативними реалізаціями. Для продакшн-рівня рекомендуємо stomp_dart_client якщо сервер використовує STOMP, або кастомний manager з тими ж принципами reconnect.
Аутентифікація та оновлення токенів
WebSocket-з'єднання аутентифікується один раз при встановленні — через Authorization заголовок у handshake або першим повідомленням після підключення (auth frame). JWT-токен може протухнути за час сесії — потрібна логіка оновлення токена та перепідключення. Ми реалізуємо таймер, що запускає оновлення токена за 1 хвилину до закінчення, з наступним перепідключенням.
Що входить в роботу
- Архітектурна схема взаємодії WebSocket та push-сповіщень
- Вихідний код WebSocket-клієнта (Swift/Kotlin/Dart) з документацією
- Налаштування heartbeat та exponential backoff
- Інтеграція з APNs та FCM
- Тестування на реальних пристроях у різних мережевих умовах
- Інструкція з експлуатації та код-рев'ю
Процес роботи над інтеграцією
- Аналіз вимог: визначення сценаріїв чату, протоколу (Raw WebSocket/STOMP/Socket.IO).
- Проектування архітектури: вибір стеку, схема аутентифікації, heartbeat.
- Реалізація WebSocket-клієнта: код під платформу, reconnect, обробка помилок.
- Інтеграція push: налаштування APNs/FCM, зв'язок з WebSocket-сесією.
- Тестування на реальних пристроях: зміна мережі, background, поганий сигнал.
- Деплой у Store та моніторинг стабільності.
Терміни та гарантії
Термін реалізації повноцінного WebSocket-клієнта з reconnect, heartbeat, обробкою зміни мережі та push — від 4 до 8 днів. Ми гарантуємо стабільність з'єднання в 99.9% сесій при нормальних мережевих умовах. Оцінимо ваш проєкт за 1 день — просто зв'яжіться з нами. Отримайте консультацію з архітектури чату безкоштовно. Замовте інтеграцію WebSocket-чату під ключ — ваші користувачі отримають миттєві повідомлення без затримок.







