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
```
效果在server端可以看到连接建立成功
效果在server端可以看到连接建立成功"

View File

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

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