乐趣区

关于websocket:用golang写一个简易聊天室

这里 websocket 库用的是 github.com/lxzan/gws. 实现上十分的简介, 没有任何依赖; 事件驱动; 反对中间件; 每个连贯自带音讯队列, 不会被单条音讯的解决阻塞通信.

  • 外围接口如下, 是不是相熟的滋味

    type EventHandler interface {OnRecover(socket *Conn, exception interface{})
      OnOpen(socket *Conn)
      OnClose(socket *Conn, code Code, reason []byte)
      OnMessage(socket *Conn, m *Message)
      OnError(socket *Conn, err error)
      OnPing(socket *Conn, m []byte)
      OnPong(socket *Conn, m []byte)
    }
  • 聊天室代码

    package main
    
    import (
      "encoding/json"
      "github.com/lxzan/gws"
      "net/http"
      "sync"
    )
    
    var handler = &Handler{sessions: sync.Map{}}
    
    type Handler struct {sessions sync.Map}
    
    func (h *Handler) OnRecover(socket *gws.Conn, exception interface{}) {}
    
    // 把连贯保留到 sync.Map, 用于 websocket 连贯之间的通信
    func (h *Handler) OnOpen(socket *gws.Conn) {name, _ := socket.Storage.Get("name")
      h.sessions.Store(name.(string), socket)
    }
    
    func (h *Handler) OnClose(socket *gws.Conn, code gws.Code, reason []byte) {}
    
    // 通信格局
    type Request struct {
      To      string `json:"to"`
      Message string `json:"message"`
    }
    
    func (h *Handler) OnMessage(socket *gws.Conn, m *gws.Message) {
      var request Request
      json.Unmarshal(m.Bytes(), &request)
    
      me, _ := socket.Storage.Get("name")
      if me.(string) == request.To {socket.Write(m.MessageType(), m.Bytes())
          m.Close()} else {if receiver, ok := h.sessions.Load(request.To); ok {h.OnMessage(receiver.(*gws.Conn), m)
          }
      }
    }
    
    func (h *Handler) OnError(socket *gws.Conn, err error) {}
    
    func (h *Handler) OnPing(socket *gws.Conn, m []byte) {}
    
    func (h *Handler) OnPong(socket *gws.Conn, m []byte) {}
    
    func main() {
      var upgrader = gws.Upgrader{
          ServerOptions: &gws.ServerOptions{
              LogEnabled:      true,
              CompressEnabled: false,
          },
          
          // 用户名由 url 带进来, 存到 storage 外面
          CheckOrigin: func(r *gws.Request) bool {r.Storage.Put("name", r.URL.Query().Get("name"))
              return true
          },
      }
    
      http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {upgrader.Upgrade(w, r, handler)
      })
    
      http.ListenAndServe(":3000", nil)
    }
退出移动版