логотип PurpleSchool
логотип PurpleSchool

Сетевые протоколы в Go

Автор

Александр Гольцман

Сетевое взаимодействие играет ключевую роль в современных приложениях, обеспечивая обмен данными между клиентами и серверами. Go предоставляет мощный набор инструментов для работы с различными сетевыми протоколами, включая TCP, UDP, HTTP и WebSocket.

В этой статье я покажу, как в Go реализовать сетевое взаимодействие, объясню принципы работы каждого протокола и продемонстрирую примеры их использования.

Принципы работы сетевых протоколов

Прежде чем переходить к конкретным примерам, давайте разберемся, как работают основные сетевые протоколы.

  • TCP (Transmission Control Protocol) — обеспечивает надежную и упорядоченную доставку данных. Соединение устанавливается перед началом передачи, что гарантирует целостность данных. TCP широко применяется в веб-приложениях, базах данных и других критически важных сервисах.
  • UDP (User Datagram Protocol) — более быстрый, но ненадежный протокол. Он не требует установления соединения и не гарантирует доставку пакетов. Используется в VoIP, стриминге и онлайн-играх, где важна минимальная задержка.
  • HTTP (HyperText Transfer Protocol) — протокол для взаимодействия между веб-клиентами и серверами. HTTP работает поверх TCP и является основой интернета.
  • WebSocket — протокол, позволяющий установить постоянное соединение между клиентом и сервером, что делает его удобным для чатов, потоковой передачи данных и других интерактивных приложений.

Работа с TCP в Go

Go предоставляет удобный интерфейс для работы с TCP через пакет net. TCP-соединение состоит из трех этапов:

  1. Установка соединения (TCP-handshake).
  2. Передача данных.
  3. Закрытие соединения.

Смотрите, как можно реализовать TCP-сервер:

listener, err := net.Listen("tcp", ":8080")
if err != nil {
    log.Fatal(err)
}
defer listener.Close()

for {
    conn, err := listener.Accept()
    if err != nil {
        log.Println("Ошибка при подключении:", err)
        continue
    }
    go handleConnection(conn)
}

Здесь сервер прослушивает порт 8080, принимает входящие соединения и передает их в обработчик.

А вот пример TCP-клиента, который устанавливает соединение с сервером и отправляет запрос:

conn, err := net.Dial("tcp", "example.com:80")
if err != nil {
    log.Fatal(err)
}
defer conn.Close()

message := "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"
conn.Write([]byte(message))

response := make([]byte, 1024)
n, _ := conn.Read(response)
fmt.Println(string(response[:n]))

TCP идеально подходит для приложений, где критически важна целостность данных, например, в банковских системах или системах передачи файлов.

Работа с UDP в Go

UDP обеспечивает низкую задержку при передаче данных, но не гарантирует их доставку. Это делает его полезным для приложений, где скорость важнее надежности.

Вот как выглядит базовый UDP-сервер:

addr, err := net.ResolveUDPAddr("udp", ":8080")
conn, err := net.ListenUDP("udp", addr)
if err != nil {
    log.Fatal(err)
}
defer conn.Close()

buffer := make([]byte, 1024)
for {
    n, clientAddr, _ := conn.ReadFromUDP(buffer)
    fmt.Println("Получено:", string(buffer[:n]), "от", clientAddr)
}

А это UDP-клиент, отправляющий сообщение серверу:

serverAddr, err := net.ResolveUDPAddr("udp", "example.com:1234")
conn, err := net.DialUDP("udp", nil, serverAddr)
if err != nil {
    log.Fatal(err)
}
defer conn.Close()

message := []byte("ping")
conn.Write(message)

UDP активно используется в онлайн-играх, потоковом видео и IoT-устройствах.

Работа с HTTP в Go

Подробнее эту тему мы осветили в этой статье. HTTP — один из самых популярных сетевых протоколов, обеспечивающий передачу данных в формате запросов и ответов.

Смотрите, как просто создать HTTP-сервер в Go:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "Привет, Go!")
})
http.ListenAndServe(":8080", nil)

А вот пример отправки HTTP-запроса с помощью net/http:

resp, err := http.Get("https://api.example.com/data")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))

HTTP является основой REST API и большинства веб-приложений.

Работа с WebSocket в Go

WebSocket позволяет поддерживать постоянное соединение между клиентом и сервером, что делает его удобным для чатов, потокового обмена данными и игр.

В Go для работы с WebSocket используется библиотека github.com/gorilla/websocket.

Смотрите, как создать WebSocket-сервер:

var upgrader = websocket.Upgrader{}

http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
    conn, _ := upgrader.Upgrade(w, r, nil)
    defer conn.Close()

    for {
        _, msg, _ := conn.ReadMessage()
        fmt.Println("Получено сообщение:", string(msg))
    }
})

http.ListenAndServe(":8080", nil)

Этот сервер принимает WebSocket-соединения и обрабатывает входящие сообщения.

Заключение

В Go работа с сетевыми протоколами реализована через стандартные пакеты net и net/http, а также сторонние библиотеки, такие как gorilla/websocket.

Давайте подведем итоги:

  • TCP — надежный и упорядоченный, подходит для критически важных приложений.
  • UDP — быстрый, но ненадежный, используется там, где важна скорость.
  • HTTP — основной протокол веба, применяется для REST API и клиент-серверных приложений. Подробнее — здесь.
  • WebSocket — обеспечивает двустороннюю связь в реальном времени.

Выбор протокола зависит от требований к надежности, скорости и поддержке соединений. Если вам важно гарантированное получение данных — используйте TCP. Если важнее скорость — UDP. Для веба удобен HTTP, а для интерактивных сервисов — WebSocket.

Смотрите, какие задачи вам нужно решить, и выбирайте подходящий сетевой протокол в Go.

Переменные в GolangСтрелочка вправо

Все гайды по Golang

Работа с YAML в GolangПреобразование типов в GolangКонвертация структур в JSON в GolangStrconv в GolangИспользование пакета SQLx для работы с базами данных в GolangРазбираемся с SQL в GolangРазделение строк с помощью функции split в GolangSort в GoПоиск и замена строк в Go - GolangИспользование пакета reflect в GolangРабота с PostgreSQL в GoPointers в GolangПарсинг в GoРабота со списками (list) в GolangПреобразование int в string в GolangРабота с числами с плавающей точкой в GolangРабота с полями в GolangИспользование enum в GolangОбработка JSON в GoЧтение и запись CSV-файлов в GolangРабота с cookie в GolangРегистры в GoКэширование данных в GolangПреобразование byte в string в GolangByte в GoИспользование bufio для работы с потоками данных в GolangДобавление данных и элементов (add) в Go
Логирование в Golang. Zap, Logrus, Loki, GrafanaРабота с Docker-контейнерами в GoИспользование pprof в GolangМеханизмы синхронизации в GolangРабота с пакетом S3 в GolangМониторинг Golang приложений с помощью PrometheusОптимизация проектов на GoМиграции базы данных в GolangПаттерны проектирования в GolangОркестрация контейнеров Go с Kubernetes + DockerGjGo Playground и компилятор GolangИспользование go mod init для создания модулей GolangРабота с переменными окружения (env) в GolangКоманда go build в GolangАвтоматизация Golang проектов — CI/CD с GitLab CI и JenkinsОтладка кода в GolangЧтение и использование конфигурации в приложениях на GolangКомпиляция в GolangКак развернуть Go-приложение на облаке AWSАутентификация в Golang
Сетевые протоколы в GoПеременные в GolangЗначения в GolangДженерик %T и его применение в GolangТипы данных в GolangИспользование tls в GolangИспользование tag в структурах GolangSwitch в GoСтроки в GolangРабота с потоками (stream) в GolangSelect в GoРуны в GoРабота с пакетом params в GolangКонвертация строк в числа в GolangNull, Nil, None, 0 в GoНаименования переменных, функций и структур в GoInt в GolangУстановка GolangЧтение и установка HTTP заголовков в GolangMethods в GolangGoLand — IDE для разработки на Golang от JetBrainsОбработка «not found» в GolangFloat в GolangФлаги командной строки в Go (Golang)Запуск внешних команд в GolangОбработка ошибок в GoИспользование defer в GolangЗначения default в GolangГенерация кода в GoФорматирование кода в GolangЧистая архитектура в GolangКаналы (channels) в GolangПолучение body из HTTP запроса в Golang
Открыть базу знаний