Socket.IO работа на Go

Socket.IO построен на базе протокола WebSocket и обеспечивает дополнительные гарантии, например, возврат к HTTP long-polling.

Socket.IO работа на Go

До этого момента мы ввели новый термин: WebSocket .

Давайте сначала разберемся, что такое протокол WebSocket, а затем в оставшейся части статьи рассмотрим Socket.IO с примерами.

WebSocket позволяет создавать приложения “реального времени”, которые работают быстрее и требуют меньше накладных расходов, чем традиционные протоколы API. Иногда называемый протоколом компьютерной связи высшего класса, WebSocket необходим для организации канала связи клиент-сервер.

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

В настоящее время в W3C осуществляется стандартизация API Web Sockets. Черновой вариант стандарта этого протокола утверждён IETF.

WebSocket разработан для реализациии в веб-браузерах и веб-серверах, но он может быть использован для любого клиентского или серверного приложения. Протокол WebSocket — это независимый протокол, основанный на протоколе TCP. Он делает возможным более тесное взаимодействие между браузером и веб-сайтом, способствуя распространению интерактивного содержимого и созданию приложений реального времени.

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

Socket.IO работа на Go

Что такое Socket.IO?

Socket.IO – это библиотека, которая позволяет осуществлять связь между клиентом и сервером с низкой задержкой, двунаправленную и основанную на событиях.

Как это работает?

Двунаправленный канал между сервером Socket.IO и клиентом Socket.IO устанавливается с помощью WebSocket-соединения, когда это возможно, и будет использовать HTTP long-polling в качестве запасного варианта.

Кодовая база Socket.IO разделена на два различных уровня:

  • низкоуровневый: то, что мы называем Engine.IO, движок внутри Socket.IO
  • высокоуровневый API: сам Socket.IO
  • Engine.IO отвечает за установление низкоуровневого соединения между сервером и клиентом.

Он обрабатывает:

  • различные транспорты и механизм обновления
  • обнаружение разрыва соединения
  • По умолчанию клиент устанавливает соединение с HTTP-транспортом с длинным опросом.

Но почему?

Хотя WebSocket, безусловно, является лучшим способом установления двунаправленной связи, опыт показывает, что не всегда возможно установить WebSocket-соединение из-за корпоративных прокси-серверов, персональных брандмауэров, антивирусных программ…

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

Подводя итог, можно сказать, что Engine.IO в первую очередь фокусируется на надежности и пользовательском опыте, а во вторую – на маргинальных потенциальных улучшениях UX и увеличении производительности сервера.

Для обновления клиент должен:

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

Реализация с помощью Go

Настройка простого сервера на golang:

go mod init myproject
go get  github.com/googollee/go-socket.io@v1.0.1

Код на стороне сервера:

package main

import (
 "fmt"
 "log"
 "net/http"

 socketio "github.com/googollee/go-socket.io"
)

func main() {
 server, err := socketio.NewServer(nil)
 if err != nil {
  log.Fatal("error establishing new socketio server")
 }

 server.On("connection", func(so socketio.Socket) {
  log.Println("On connection established")

  so.Join("mychat") //join the room with the above socketio connection

  so.On("chat message", func(msg string) {
   log.Println("messge received: " + msg)
   so.BroadcastTo("mychat", "chat message", msg) //broadcasting the message to the room so all the clients connected can get it
  })
 })

 fmt.Println("Server running on localhost: 5001")

 //create a folder with name static and within that index.html
 fs := http.FileServer(http.Dir("static"))
 http.Handle("/", fs)

 http.Handle("/socket.io/", server)

 log.Fatal(http.ListenAndServe(":5001", nil))

}

Я создал папку с именем static и создал в ней index.html с приведенным ниже кодом фронтенда:

Мы создадим базовое фронтенд-приложение, которое будет транслировать сообщение “hello world!” в наше событие “chat message”.

Здесь мы также читаем на этом событии в том же клиенте все, что транслируется, но это можно сделать и на отдельном фронтенд-клиенте.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Go WebSocket Tutorial</title>
  </head>
  <body>
    <h2>Hello World</h2>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script>
    <script>
      const socket = io("http://localhost:5001/socket.io/");
      
      socket.emit("chat message", "hello world!") //emitting the message from 1 client

      //all the client reading on that event will get that message once broadcasted
      socket.on("chat message", (msg) => {
        console.log("Client side: " + msg)
      })
    </script>
  </body>
</html>

Теперь запустите сервер с помощью:

go run app.go

Перенаправьте на localhost:5001 и вы увидите, что нужные журналы выводятся как на стороне сервера, так и на стороне клиента.

В моем случае я получил:

Server running on localhost: 5001
2023/07/05 01:53:35 On connection established
2023/07/05 01:53:35 On connection established
2023/07/05 01:53:35 On connection established
2023/07/05 01:53:35 On connection established
2023/07/05 01:53:35 messge received: hello world!
+1
0
+1
0
+1
0
+1
0
+1
2

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *