From 49a696b5827cf4c3091e3a9fd6f65469f56a1e75 Mon Sep 17 00:00:00 2001 From: wandoubaba Date: Sun, 24 Nov 2024 12:12:35 +0800 Subject: [PATCH] =?UTF-8?q?IM-System=E7=89=88=E6=9C=AC0.2=EF=BC=8C?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=AE=A2=E6=88=B7=E7=AB=AF=E4=B8=8A=E7=BA=BF?= =?UTF-8?q?=E7=9A=84=E6=B6=88=E6=81=AF=E5=B9=BF=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bilibili/aceld/IM-System/README.md | 2 +- bilibili/aceld/IM-System/server.go | 75 ++++++++++++++++++++++-------- bilibili/aceld/IM-System/user.go | 32 +++++++++++++ 3 files changed, 89 insertions(+), 20 deletions(-) create mode 100644 bilibili/aceld/IM-System/user.go diff --git a/bilibili/aceld/IM-System/README.md b/bilibili/aceld/IM-System/README.md index d4316d9..c50e790 100644 --- a/bilibili/aceld/IM-System/README.md +++ b/bilibili/aceld/IM-System/README.md @@ -22,4 +22,4 @@ go build -o server main.go server.go nc 127.0.0.1 8888 ``` -效果:在server端可以看到连接建立成功 +效果:在server端可以看到“连接建立成功" diff --git a/bilibili/aceld/IM-System/server.go b/bilibili/aceld/IM-System/server.go index 0210a65..9358c66 100644 --- a/bilibili/aceld/IM-System/server.go +++ b/bilibili/aceld/IM-System/server.go @@ -3,48 +3,85 @@ package main import ( "fmt" "net" + "sync" ) type Server struct { - Ip string - Port int + Ip string + Port int + OnlineMap map[string]*User // 在线用户列表 + mapLock sync.RWMutex // OnlineMap读写锁 + Message chan string // 用户消息管道 } -// Server类的成员方法Handler: 处理当前连接的业务 +// 创建一个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 +} + +// server类的成员方法:监听Message广播消息channel的goroutine, 一旦有消息就发送给全部的在线User +func (server *Server) ListenMessage() { + for { + msg := <-server.Message + // 将msg发送给全部的在线User + server.mapLock.Lock() + for _, cli := range server.OnlineMap { + cli.C <- msg + } + server.mapLock.Unlock() + } +} + +// server类的成员方法:向所有在线客户端发送广播 +func (server *Server) BroadCast(user *User, msg string) { + sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg + server.Message <- sendMsg +} + +// server类的成员方法:处理客户端连接 func (server *Server) Handler(conn net.Conn) { // 当前连接的业务 - fmt.Println("连接建立成功") + fmt.Println("客户端连接建立成功") + + // 用户上线, 将用户加入到OnlineMap中 + user := NewUser(conn) + server.mapLock.Lock() + server.OnlineMap[user.Name] = user + server.mapLock.Unlock() + // 广播当前用户的上线消息 + server.BroadCast(user, "已上线") + // 当前handler阻塞 + select {} } -// Server类的成员方法Start:启动服务器的接口s +// Server类的成员方法:启动服务器的接口 func (server *Server) Start() { - // socket lister + // socket listen listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", server.Ip, server.Port)) if err != nil { fmt.Println("net.Listen err: ", err) - return } + // close listen socket defer listener.Close() - + // 启动监听Message的goroutine + go server.ListenMessage() + // 死循环实现监听 for { // accept conn, err := listener.Accept() if err != nil { - fmt.Println("listener accept err: ", err) + fmt.Println("listener accept err:", err) continue } // do handler go server.Handler(conn) + } - // close listen socket -} - -// 创建一个server接口 -func NewServer(ip string, port int) *Server { - server := &Server{ - Ip: ip, - Port: port, - } - return server } diff --git a/bilibili/aceld/IM-System/user.go b/bilibili/aceld/IM-System/user.go new file mode 100644 index 0000000..51e9f2a --- /dev/null +++ b/bilibili/aceld/IM-System/user.go @@ -0,0 +1,32 @@ +package main + +import "net" + +type User struct { + Name string + Addr string + C chan string + conn net.Conn +} + +// 创建一个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 +} + +// User类的成员方法: 监听消息 +func (user *User) ListenMessage() { + for { + msg := <-user.C + user.conn.Write([]byte(msg + "\n")) + } +}