golang-im聊天
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

106 lines
1.7 KiB

  1. package connect
  2. import (
  3. "container/list"
  4. "gim/pkg/pb"
  5. "sync"
  6. )
  7. var RoomsManager sync.Map
  8. // SubscribedRoom 订阅房间
  9. func SubscribedRoom(conn *Conn, roomId int64) {
  10. if roomId == conn.RoomId {
  11. return
  12. }
  13. oldRoomId := conn.RoomId
  14. // 取消订阅
  15. if oldRoomId != 0 {
  16. value, ok := RoomsManager.Load(oldRoomId)
  17. if !ok {
  18. return
  19. }
  20. room := value.(*Room)
  21. room.Unsubscribe(conn)
  22. if room.Conns.Front() == nil {
  23. RoomsManager.Delete(oldRoomId)
  24. }
  25. return
  26. }
  27. // 订阅
  28. if roomId != 0 {
  29. value, ok := RoomsManager.Load(roomId)
  30. var room *Room
  31. if !ok {
  32. room = NewRoom(roomId)
  33. RoomsManager.Store(roomId, room)
  34. } else {
  35. room = value.(*Room)
  36. }
  37. room.Subscribe(conn)
  38. return
  39. }
  40. }
  41. // PushRoom 房间消息推送
  42. func PushRoom(roomId int64, message *pb.MessageSend) {
  43. value, ok := RoomsManager.Load(roomId)
  44. if !ok {
  45. return
  46. }
  47. value.(*Room).Push(message)
  48. }
  49. type Room struct {
  50. RoomId int64 // 房间ID
  51. Conns *list.List // 订阅房间消息的连接
  52. lock sync.RWMutex
  53. }
  54. func NewRoom(roomId int64) *Room {
  55. return &Room{
  56. RoomId: roomId,
  57. Conns: list.New(),
  58. }
  59. }
  60. // Subscribe 订阅房间
  61. func (r *Room) Subscribe(conn *Conn) {
  62. r.lock.Lock()
  63. defer r.lock.Unlock()
  64. conn.Element = r.Conns.PushBack(conn)
  65. conn.RoomId = r.RoomId
  66. }
  67. // Unsubscribe 取消订阅
  68. func (r *Room) Unsubscribe(conn *Conn) {
  69. r.lock.Lock()
  70. defer r.lock.Unlock()
  71. r.Conns.Remove(conn.Element)
  72. conn.Element = nil
  73. conn.RoomId = 0
  74. }
  75. // Push 推送消息到房间
  76. func (r *Room) Push(message *pb.MessageSend) {
  77. r.lock.RLock()
  78. defer r.lock.RUnlock()
  79. element := r.Conns.Front()
  80. for {
  81. conn := element.Value.(*Conn)
  82. conn.Send(pb.PackageType_PT_MESSAGE, 0, message, nil)
  83. element = element.Next()
  84. if element == nil {
  85. break
  86. }
  87. }
  88. }