Введение
Иногда воникают задачи отобразить какие-либо изменения на клиенте, которые произошли на сервере, например при сборе телеметрии, отображать перемещение объекта или изменение его показателей. Для этой задачи часто используют протокол WebSocket.
В статье я хочу показать как реализовать websocket на Go, который, для реалистичности, будет отдавать GeoJSON.
Реализация
Для реализации веб сокета будут использоваться следующие библиотеки
- Echo - минималистичный web фреймворк.
- Websocket - Реализация протокола websocket на Go.
- go.geojson - декодер GeoJSON на Go
Код сокета приведен ниже:
package main
import (
"github.com/gorilla/websocket"
"github.com/labstack/echo"
"github.com/labstack/echo/middleware"
"github.com/labstack/gommon/log"
"github.com/paulmach/go.geojson"
"net/http"
"time"
)
var upgrader = websocket.Upgrader{}
func main() {
e := echo.New()
e.Use(middleware.Logger())
e.Pre(middleware.RemoveTrailingSlash())
e.Logger.SetLevel(log.DEBUG)
e.GET("/ws", geoWebsocket)
e.Logger.Fatal(e.Start("localhost:8081"))
}
func geoWebsocket(c echo.Context) error {
upgrader.CheckOrigin = func(r *http.Request) bool { return true }
ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
if err != nil {
return err
}
defer ws.Close()
geojsonPoint := `{
"type": "feature",
"geometry": {
"type": "point",
"coordinates": [
37.5334919,
55.6077987
]
},
"properties": {
"client": "30457412",
"nph_request_id": "577341",
"nav_time": "2019-02-22t18:31:22.095480z"
}
}`
point, err := geojson.UnmarshalFeature([]byte(geojsonPoint))
if err != nil {
c.Logger().Fatal(err)
}
for {
if geoPkg, err := point.MarshalJSON(); err != nil {
c.Logger().Error(err)
} else {
c.Logger().Debug("Send: ", string(geoPkg))
if err := ws.WriteMessage(websocket.TextMessage, geoPkg); err != nil {
c.Logger().Error(err)
}
}
time.Sleep(1 * time.Second)
}
}
В данном коде сначала создается экземпляр web приложения, затем к нему подключаются логгер, и middleware для удаления последнего слэша в адресе.
После этого на GET запрос привязвыется обработчк, который содержит сам websocket.
Затем мы разбираем строку с помощью geojson и каждую секунду отправляем эту точку в websocket.
Как видно код получился не самый сложный.
Проверить что веб сокет работает, можно через простенький html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>WebSocket</title>
</head>
<body>
<p id="output"></p>
<script>
ws = new WebSocket('ws://localhost:8081/ws');
ws.onopen = function() {
console.log('Connected')
};
ws.onmessage = function(evt) {
var out = document.getElementById('output');
console.log(evt);
out.innerHTML += evt.data + '<br>';
};
</script>
</body>
</html>
Если запустить websoсket, а затем открыть в браузере html файл приведенный выше, то можно наблюдать следующее:
Заключение
В результате получился доволь просто, но функциональный websocket, который при минимальной доработке может использоваться в продуктовой разработке.
comments powered by Disqus