如果异常断开连接,Websocket 会冻结



我创建了一个发布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()
}        

有关如何避免在客户端上阻塞的示例,请参阅 Gorilla 聊天应用程序。

关键部分是:

  • 使用缓冲通道发送到客户端。您的应用程序已经在执行此操作。

  • 使用选择/默认值发送到客户端以避免阻塞。假设客户端在写入时被阻止,当客户端无法立即接收消息时。在这种情况下,关闭客户端的通道,以使客户端的写入循环退出。

  • 写一个截止日期。

最新更新