@Kagtaviy

Как работать с gorilla/websocket?

Здравствуйте, не могу разобраться с 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);
			};
		});
  • Вопрос задан
  • 2313 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы