IM-System版本0.2,实现客户端上线的消息广播

This commit is contained in:
wandoubaba 2024-11-24 12:12:35 +08:00
parent c31d0ba789
commit 49a696b582
3 changed files with 89 additions and 20 deletions

View File

@ -22,4 +22,4 @@ go build -o server main.go server.go
nc 127.0.0.1 8888 nc 127.0.0.1 8888
``` ```
效果在server端可以看到连接建立成功 效果在server端可以看到连接建立成功"

View File

@ -3,29 +3,75 @@ package main
import ( import (
"fmt" "fmt"
"net" "net"
"sync"
) )
type Server struct { type Server struct {
Ip string Ip string
Port int 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) { 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() { func (server *Server) Start() {
// socket lister // socket listen
listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", server.Ip, server.Port)) listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", server.Ip, server.Port))
if err != nil { if err != nil {
fmt.Println("net.Listen err: ", err) fmt.Println("net.Listen err: ", err)
return
} }
// close listen socket
defer listener.Close() defer listener.Close()
// 启动监听Message的goroutine
go server.ListenMessage()
// 死循环实现监听
for { for {
// accept // accept
conn, err := listener.Accept() conn, err := listener.Accept()
@ -35,16 +81,7 @@ func (server *Server) Start() {
} }
// do handler // do handler
go server.Handler(conn) go server.Handler(conn)
} }
// close listen socket
}
// 创建一个server接口
func NewServer(ip string, port int) *Server {
server := &Server{
Ip: ip,
Port: port,
}
return server
} }

View File

@ -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"))
}
}