ws.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. package initialize
  2. import (
  3. "confrontation-training/global"
  4. "encoding/json"
  5. "github.com/gin-gonic/gin"
  6. "github.com/gorilla/websocket"
  7. log "github.com/sirupsen/logrus"
  8. "net/http"
  9. )
  10. // ClientManager is a websocket manager
  11. type ClientManager struct {
  12. Clients map[string]*Client
  13. Broadcast chan []byte
  14. Register chan *Client
  15. Unregister chan *Client
  16. }
  17. // Client is a websocket client
  18. type Client struct {
  19. ID string
  20. Socket *websocket.Conn
  21. Send chan []byte
  22. }
  23. // Message is return msg
  24. type Message struct {
  25. Sender string `json:"sender,omitempty"`
  26. Recipient string `json:"recipient,omitempty"`
  27. Content string `json:"content,omitempty"`
  28. }
  29. // Manager define a ws server manager
  30. var Manager = ClientManager{
  31. Broadcast: make(chan []byte),
  32. Register: make(chan *Client),
  33. Unregister: make(chan *Client),
  34. Clients: make(map[string]*Client),
  35. }
  36. // Start is 项目运行前, 协程开启start -> go Manager.Start()
  37. func (manager *ClientManager) Start() {
  38. for {
  39. log.Infoln("<---管道通信--->")
  40. select {
  41. case conn := <-Manager.Register:
  42. log.Infof("新用户加入:%v", conn.ID)
  43. Manager.Clients[conn.ID] = conn
  44. jsonMessage, _ := json.Marshal(&Message{Content: "Successful connection to socket service"})
  45. conn.Send <- jsonMessage
  46. case conn := <-Manager.Unregister:
  47. log.Infof("用户离开:%v", conn.ID)
  48. if _, ok := Manager.Clients[conn.ID]; ok {
  49. jsonMessage, _ := json.Marshal(&Message{Content: "A socket has disconnected"})
  50. conn.Send <- jsonMessage
  51. close(conn.Send)
  52. delete(Manager.Clients, conn.ID)
  53. }
  54. case message := <-Manager.Broadcast:
  55. MessageStruct := Message{}
  56. err := json.Unmarshal(message, &MessageStruct)
  57. if err != nil {
  58. panic(err)
  59. return
  60. }
  61. for id, conn := range Manager.Clients {
  62. if id != creatId(MessageStruct.Recipient, MessageStruct.Sender) {
  63. continue
  64. } else {
  65. select {
  66. case conn.Send <- message:
  67. default:
  68. close(conn.Send)
  69. delete(Manager.Clients, conn.ID)
  70. }
  71. }
  72. }
  73. }
  74. }
  75. }
  76. func creatId(uid, touid string) string {
  77. return uid + "_" + touid
  78. }
  79. func (c *Client) Read() {
  80. //defer func() {
  81. // Manager.Unregister <- c
  82. // c.Socket.Close()
  83. //}()
  84. for {
  85. c.Socket.PongHandler()
  86. _, message, err := c.Socket.ReadMessage()
  87. if err != nil {
  88. Manager.Unregister <- c
  89. c.Socket.Close()
  90. break
  91. }
  92. //log.Infof("读取到客户端的信息:%s", string(message))
  93. Manager.Broadcast <- message
  94. }
  95. }
  96. func (c *Client) Write() {
  97. //defer func() {
  98. // c.Socket.Close()
  99. //}()
  100. for {
  101. select {
  102. case message, ok := <-c.Send:
  103. if !ok {
  104. c.Socket.WriteMessage(websocket.CloseMessage, []byte{})
  105. return
  106. }
  107. global.Log4J.Info("发送到到客户端的信息:", string(message))
  108. c.Socket.WriteMessage(websocket.TextMessage, message)
  109. }
  110. }
  111. }
  112. // WsHandler TestHandler socket 连接 中间件 作用:升级协议,用户验证,自定义信息等
  113. func WsHandler(c *gin.Context) {
  114. uid := c.Query("uid")
  115. touid := c.Query("to_uid")
  116. conn, err := (&websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}).Upgrade(c.Writer, c.Request, nil)
  117. if err != nil {
  118. http.NotFound(c.Writer, c.Request)
  119. return
  120. }
  121. //可以添加用户信息验证
  122. client := &Client{
  123. ID: creatId(uid, touid),
  124. Socket: conn,
  125. Send: make(chan []byte),
  126. }
  127. Manager.Register <- client
  128. go client.Read()
  129. go client.Write()
  130. }