Здравствуйте, не могу разобраться с websocket'ами. А именно, не понимаю как все должно работать. Пытался делать по этому уроку
https://www.jonathan-petitcolas.com/2015/01/27/pla...
Не понимаю:
1. Как правильно отправлять и принимать сообщения от клиента?
2. Зачем нужно делать go h.run() - в main и почему нельзя просто вызывать функцию serveWs по запросу на /chat
3. Почему соединение закрывается в течении 1-ой минуты, если даже вкладка не закрыта. Или когда клиент отправляет/получает данные то соединение снова восстанавливаться?
Роутер:
r := mux.NewRouter()
r.HandleFunc("/chat", ws.ServeWs)
client.go
package ws
import (
"log"
"net/http"
"time"
"github.com/gorilla/websocket"
)
const (
writeWait = 10 * time.Second
pongWait = 60 * time.Second
pingPeriod = (pongWait * 9) / 10
maxMessageSize = 1024 * 1024
)
type client struct {
ws *websocket.Conn
send chan []byte
}
var upgrader = websocket.Upgrader{
ReadBufferSize: maxMessageSize,
WriteBufferSize: maxMessageSize,
}
func (c *client) readPump() {
defer func() {
h.unregister <- c
c.ws.Close()
}()
c.ws.SetReadLimit(maxMessageSize)
c.ws.SetReadDeadline(time.Now().Add(pongWait))
c.ws.SetPongHandler(func(string) error {
c.ws.SetReadDeadline(time.Now().Add(pongWait))
return nil
})
for {
_, message, err := c.ws.ReadMessage()
if err != nil {
break
}
h.broadcast <- string(message)
}
}
func (c *client) writePump() {
ticker := time.NewTicker(pingPeriod)
defer func() {
ticker.Stop()
c.ws.Close()
}()
for {
select {
case message, ok := <-c.send:
if !ok {
c.write(websocket.CloseMessage, []byte{})
return
}
if err := c.write(websocket.TextMessage, message); err != nil {
return
}
case <-ticker.C:
if err := c.write(websocket.PingMessage, []byte{}); err != nil {
return
}
}
}
}
func (c *client) write(mt int, message []byte) error {
c.ws.SetWriteDeadline(time.Now().Add(writeWait))
return c.ws.WriteMessage(mt, message)
}
func ServeWs(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, "Method not allowed", 405)
return
}
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println(err)
return
}
c := &client{
send: make(chan []byte, maxMessageSize),
ws: ws,
}
h.register <- c
go c.writePump()
c.readPump()
}
hub.go
package ws
type hub struct {
clients map[*client]bool
broadcast chan string
register chan *client
unregister chan *client
content string
}
var h = hub{
broadcast: make(chan string),
register: make(chan *client),
unregister: make(chan *client),
clients: make(map[*client]bool),
content: "",
}
func (H *hub) Run() {
for {
select {
case c := <-h.register:
h.clients[c] = true
c.send <- []byte(h.content)
break
case c := <-h.unregister:
_, ok := h.clients[c]
if ok {
delete(h.clients, c)
close(c.send)
}
break
case m := <-h.broadcast:
h.content = m
h.broadcastMessage()
break
}
}
}
func (h *hub) broadcastMessage() {
for c := range h.clients {
select {
case c.send <- []byte(h.content):
break
default:
close(c.send)
delete(h.clients, c)
}
}
}
Js
var ws = new WebSocket("ws://domain.ru/chat");
$(function() {
ws.onopen = function() {
console.log("Подключенно");
};
ws.onclose = function() {
console.log("Отключенно");
};
});
$('msg').click(function() {
ws.onmessage = function(evt) {
console.log("Data " + evt.data);
};
});