GO - 即时通信系统(二)

164 阅读2分钟

即时通信系统版本预览:

  1. 版本一:构建基础server
  2. 版本二:用户上线功能
  3. 版本三:用户消息广播机制
  4. 版本四:用户业务层封装
  5. 版本五:在线用户查询
  6. 版本六:修改用户名
  7. 版本七:超时强踢功能
  8. 版本八:私聊功能
  9. 版本九:客户端实现

版本二:用户上线功能并向所有用户广播

user.go

  1. 定义user对象
type User struct {
   Name string
   Addr string
   C   chan string
   conn net.Conn
}
  1. 创建user对象
// 创建一个用户的Api
func NewUser(conn net.Conn) *User{
   
   userAddr := conn.RemoteAddr().String()
   
   user := &User{
      Name: userAddr,
      Addr: userAddr,
      C: make(chan string),
      conn: conn,
   }
   //启动监听当前user channel消息的goroutine
   go user.ListenMessage()

   return user
}
  1. 监听user对应的channel消息
// 监听当前User channel的,方法一旦有消息,直接发送给对方客户端
func (this *User) ListenMessage() {
   for{
      msg := <- this.C

      this.conn.Write([]byte(msg + "\n"))
   }
}

server.go

  1. 添加server对象属性
type Server struct {
   Ip string
   Port int
   // 在线用户de列表
   OnlineMap map[string]*User
   mapLock sync.RWMutex

   // 消息广播
   Message chan string
}
  1. 创建server对象
// 创建一个server的接口
func NewServer(ip string, port int) *Server {
   server := &Server{
      Ip:   ip,
      Port: port,
      OnlineMap:make(map[string]*User),
      Message:make(chan string),
   }

   return server
}
  1. 用户连接上,就进入了handler方法
func (this *Server) Handler(conn net.Conn) {
   //当前链接的业务
   fmt.Println("链接建立成功",conn)
   user := NewUser(conn)
   //用户上线,用户加入onlineMap中
   this.mapLock.Lock()
   this.OnlineMap[user.Name] = user
   this.mapLock.Unlock()

   //广播当前用户上线消息
   this.BroadCats(user, "已上线")

   // 当前handler 阻塞
   select {

   }
}
  1. 创建广播BroadCats方法
// 广播消息方法
func (this *Server) BroadCats(user *User, msg string) {
   sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg

   this.Message <- sendMsg
}
  1. 创建向所有user发送广播消息的方法
// 监听Message广播消息channel的goroutine,一旦有消息就发送给全部的在线user
func (this *Server) ListenMessage() {
   for {
      msg := <-this.Message

      // 将msg发送给全部的在线User
      this.mapLock.Lock()

      for _, cli := range this.OnlineMap {
         cli.C <- msg
      }

      this.mapLock.Unlock()
   }
}