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

huangapple go评论161阅读模式
英文:

Websocket freezes if disconnected abnormally

问题

我已经为你翻译了代码部分,请查看以下内容:

Client.go

  1. import (
  2. "github.com/gorilla/websocket"
  3. )
  4. type client struct {
  5. socket *websocket.Conn
  6. send chan *Message
  7. }
  8. func (c *client) read() {
  9. defer c.socket.Close()
  10. for {
  11. _, _, err := c.socket.ReadMessage()
  12. if err != nil {
  13. log.Info("Websocket: %s", err)
  14. break
  15. }
  16. }
  17. }
  18. func (c *client) write() {
  19. defer c.socket.Close()
  20. for msg := range c.send {
  21. err := c.socket.WriteJSON(msg)
  22. if err != nil {
  23. break
  24. }
  25. }
  26. }

Stream.go

  1. import (
  2. "net/http"
  3. "github.com/gorilla/websocket"
  4. )
  5. const (
  6. socketBufferSize = 1024
  7. messageBufferSize = 256
  8. )
  9. var upgrader = &websocket.Upgrader{
  10. ReadBufferSize: socketBufferSize,
  11. WriteBufferSize: socketBufferSize,
  12. }
  13. type Stream struct {
  14. Send chan *Message
  15. join chan *client
  16. leave chan *client
  17. clients map[*client]bool
  18. }
  19. func (s *Stream) Run() {
  20. for {
  21. select {
  22. case client := <-s.join: // joining
  23. s.clients[client] = true
  24. case client := <-s.leave: // leaving
  25. delete(s.clients, client)
  26. close(client.send)
  27. case msg := <-s.Send: // send message to all clients
  28. for client := range s.clients {
  29. client.send <- msg
  30. }
  31. }
  32. }
  33. }
  34. func (s *Stream) ServeHTTP(w http.ResponseWriter, res *http.Request) {
  35. socket, err := upgrader.Upgrade(w, res, nil)
  36. if err != nil {
  37. log.Error(err)
  38. return
  39. }
  40. defer func() {
  41. socket.Close()
  42. }()
  43. client := &client{
  44. socket: socket,
  45. send: make(chan *Message, messageBufferSize),
  46. }
  47. s.join <- client
  48. defer func() { s.leave <- client }()
  49. go client.write()
  50. client.read()
  51. }

请注意,我只翻译了代码部分,不包括问题描述部分。

英文:

I've created a simple websocket that publishes a JSON stream. I't works fine most of the time except for few cases where I think while looping through the clients to send them message, it gets hung up on a client that is being disconnected abnormally. What measure can I add to this code to mitigate it?

Client.go

  1. import (
  2. &quot;github.com/gorilla/websocket&quot;
  3. )
  4. type client struct {
  5. socket *websocket.Conn
  6. send chan *Message
  7. }
  8. func (c *client) read() {
  9. defer c.socket.Close()
  10. for {
  11. _, _, err := c.socket.ReadMessage()
  12. if err != nil {
  13. log.Info(&quot;Websocket: %s&quot;, err)
  14. break
  15. }
  16. }
  17. }
  18. func (c *client) write() {
  19. defer c.socket.Close()
  20. for msg := range c.send {
  21. err := c.socket.WriteJSON(msg)
  22. if err != nil {
  23. break
  24. }
  25. }
  26. }

Stream.go

  1. import (
  2. &quot;net/http&quot;
  3. &quot;github.com/gorilla/websocket&quot;
  4. )
  5. const (
  6. socketBufferSize = 1024
  7. messageBufferSize = 256
  8. )
  9. var upgrader = &amp;websocket.Upgrader{
  10. ReadBufferSize: socketBufferSize,
  11. WriteBufferSize: socketBufferSize,
  12. }
  13. type Stream struct {
  14. Send chan *Message
  15. join chan *client
  16. leave chan *client
  17. clients map[*client]bool
  18. }
  19. func (s *Stream) Run() {
  20. for {
  21. select {
  22. case client := &lt;-s.join: // joining
  23. s.clients[client] = true
  24. case client := &lt;-s.leave: // leaving
  25. delete(s.clients, client)
  26. close(client.send)
  27. case msg := &lt;-s.Send: // send message to all clients
  28. for client := range s.clients {
  29. client.send &lt;- msg
  30. }
  31. }
  32. }
  33. }
  34. func (s *Stream) ServeHTTP(w http.ResponseWriter, res *http.Request) {
  35. socket, err := upgrader.Upgrade(w, res, nil)
  36. if err != nil {
  37. log.Error(err)
  38. return
  39. }
  40. defer func() {
  41. socket.Close()
  42. }()
  43. client := &amp;client{
  44. socket: socket,
  45. send: make(chan *Message, messageBufferSize),
  46. }
  47. s.join &lt;- client
  48. defer func() { s.leave &lt;- client }()
  49. go client.write()
  50. client.read()
  51. }

答案1

得分: 4

请参考Gorilla Chat Application的示例,了解如何避免在客户端上阻塞。

关键部分包括:

英文:

See the Gorilla Chat Application for an example of how to avoid blocking on a client.

The key parts are:

huangapple
  • 本文由 发表于 2017年7月18日 14:08:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/45158754.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定