0Pricing
Go Academy · Урок

Управление соединениями

Обрабатывайте отключения

«Управление соединениями» — бесплатный урок Go Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Go Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Go Academy содержит 4 уроков всего.

Соединения не вечны

Клиенты закрывают вкладки, теряют Wi-Fi или аварийно завершают работу. Надёжные серверы WebSocket должны обнаруживать отключения, освобождать ресурсы и завершать горутины. Иначе возникают утечки памяти и сокетов.

Рукопожатие при закрытии

Корректное завершение отправляет кадр закрытия в обоих направлениях. gorilla сообщает об этом как об ошибке, возвращаемой ReadMessage, с кодом закрытия, который можно проверить.

if websocket.IsCloseError(err, websocket.CloseNormalClosure) {
    // graceful close
}

Поддержание соединения с помощью ping/pong

Чтобы обнаружить полуоткрытое соединение, когда узел связи исчез, не закрыв соединение, сервер периодически отправляет управляющие кадры ping и ожидает ответов pong.

conn.SetPongHandler(func(string) error {
    conn.SetReadDeadline(time.Now().Add(60 * time.Second))
    return nil
})

Предельные сроки чтения

Установите предельный срок чтения, чтобы неработающий узел связи в конце концов вызвал ошибку вместо вечной блокировки. Обновляйте этот срок при каждом поступлении pong.

conn.SetReadDeadline(time.Now().Add(60 * time.Second))

Периодические ping-сообщения

Таймер в горутине записи периодически запускает отправку ping. Если запись завершается ошибкой, соединение считается неработающим, и горутина завершается.

ticker := time.NewTicker(54 * time.Second)
defer ticker.Stop()
for range ticker.C {
    if err := conn.WriteMessage(websocket.PingMessage, nil); err != nil {
        return
    }
}

Освобождение ресурсов при завершении

Когда цикл чтения или записи завершается, удалите клиента из центрального узла и закройте соединение. defer обеспечивает надёжное выполнение этих действий даже при панике.

defer func() {
    hub.unregister <- client
    conn.Close()
}()

Две горутины на соединение

Стандартный шаблон запускает для каждого соединения readPump и writePump. Когда одна из них обнаруживает ошибку, она запускает освобождение ресурсов, которое останавливает другую, часто закрывая канал send.

Предельные сроки записи

Установите предельные сроки записи, чтобы зависшая запись не удерживала горутину вечно. Запись, для которой истёк срок ожидания, возвращает ошибку, после чего соединение следует закрыть.

conn.SetWriteDeadline(time.Now().Add(10 * time.Second))

Корректное завершение работы сервера

При завершении работы сервера отправьте каждому клиенту кадр закрытия и немного подождите. Объедините это с http.Server.Shutdown и крайним сроком контекста.

conn.WriteMessage(websocket.CloseMessage,
    websocket.FormatCloseMessage(websocket.CloseGoingAway, "bye"))

Переподключение клиента

Отключения — нормальное явление. Клиенты должны реализовать логику повторного подключения с экспоненциальной задержкой. На стороне сервера достаточно корректно обрабатывать каждое подключение и отключение.

Исполняемый пример: аналогия с обнаружением по времени ожидания

Для поддержания соединения WebSocket нужна библиотека; эта программа стандартной библиотеки моделирует проверку активности на основе крайнего срока с помощью таймера и канала.

package main

import (
    "fmt"
    "time"
)

func main() {
    pong := make(chan struct{})
    go func() {
        time.Sleep(20 * time.Millisecond) // simulate a slow/absent peer
        _ = pong                          // no pong sent -> dead connection
    }()
    select {
    case <-pong:
        fmt.Println("alive")
    case <-time.After(10 * time.Millisecond):
        fmt.Println("no pong: closing dead connection")
    }
}

Проверка

Проверьте своё понимание управления соединениями.

Повторение

Вы изучили управление соединениями:

  • Обрабатывайте рукопожатие при закрытии и проверяйте коды закрытия
  • Используйте ping/pong вместе с предельными сроками чтения и записи, чтобы обнаруживать неработающие узлы связи
  • Запускайте циклы чтения и записи; освобождайте ресурсы с помощью defer
  • Завершайте работу корректно с помощью кадров закрытия; клиенты переподключаются с экспоненциальной задержкой

Часто задаваемые вопросы

Урок «Управление соединениями» бесплатный?

Да — полный текст урока «Управление соединениями» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Go Academy, подпишись на CoddyKit PRO. Курс Go Academy содержит 4 уроков всего.

Чему я научусь в уроке «Управление соединениями»?

Обрабатывайте отключения Ты практикуешь Go Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Go Academy?

Предыдущий опыт не требуется. Go Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Управление соединениями»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Go Academy?

Да. Каждый урок Go Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы WebSocket
  2. Использование gorilla/websocket
  3. Трансляция сообщений
  4. Управление соединениями
← Назад к Go Academy