如果异常断开,Websocket会冻结

时间:2017-07-18 06:08:42

标签: go websocket gorilla

我创建了一个发布JSON流的简单websocket。我在大多数情况下工作正常,除了我认为在循环通过客户端发送消息时的几种情况,它会挂在异常断开的客户端上。我可以在此代码中添加哪些措施来缓解它?

Client.go

import (
    "github.com/gorilla/websocket"
)

type client struct {
    socket *websocket.Conn

    send chan *Message
}

func (c *client) read() {
    defer c.socket.Close()
    for {
        _, _, err := c.socket.ReadMessage()
        if err != nil {
            log.Info("Websocket: %s", err)
            break
        }
    }
}

func (c *client) write() {
    defer c.socket.Close()
    for msg := range c.send {
        err := c.socket.WriteJSON(msg)
        if err != nil {
            break
        }
    }
}

Stream.go

import (
    "net/http"

    "github.com/gorilla/websocket"
)

const (
    socketBufferSize  = 1024
    messageBufferSize = 256
)

var upgrader = &websocket.Upgrader{
    ReadBufferSize:  socketBufferSize,
    WriteBufferSize: socketBufferSize,
}

type Stream struct {
    Send chan *Message

    join chan *client

    leave chan *client

    clients map[*client]bool
}

func (s *Stream) Run() {
    for {
        select {
        case client := <-s.join: // joining
            s.clients[client] = true
        case client := <-s.leave: // leaving
            delete(s.clients, client)
            close(client.send)
        case msg := <-s.Send: // send message to all clients
            for client := range s.clients {
                client.send <- msg
            }
        }
    }
}

func (s *Stream) ServeHTTP(w http.ResponseWriter, res *http.Request) {
    socket, err := upgrader.Upgrade(w, res, nil)
    if err != nil {
        log.Error(err)
        return
    }

    defer func() {
        socket.Close()
    }()

    client := &client{
        socket: socket,
        send:   make(chan *Message, messageBufferSize),
    }

    s.join <- client
    defer func() { s.leave <- client }()

    go client.write()
    client.read()
}        

1 个答案:

答案 0 :(得分:2)

有关如何避免在客户端上阻止的示例,请参阅Gorilla Chat Application

关键部分是: