package main
import (
"net"
"fmt"
"strings"
"time"
)
//保存在线用户
var onlineMap map[string]Client = make(map[string]Client)
var message = make(chan string)
type Client struct {
C chan string
Name string
Addr string
}
func main() {
lis,e1 := net.Listen("tcp","127.0.0.1:8888")
if e1 != nil {
fmt.Println("e1 = ",e1)
return
}
defer lis.Close()
//将某个用户上线的通知发送个所有的在线用户,这里会阻塞,直到下面往message发送消息
go Manager()
for {
conn,e2 := lis.Accept()
if e2 != nil {
fmt.Println("e2 = ",e2)
continue
}
//每一个请求过来都创建一个新的协程
go HandleConn(conn)
}
}
func Manager() {
for {
msg := <- message
//遍历map,给map的每一个元素发送消息
for _,cli := range onlineMap {
//将msg信息发送给map每一个元素
cli.C <- msg
}
}
}
func HandleConn(conn net.Conn) {
defer conn.Close()
cliAddr := conn.RemoteAddr().String()
cli := Client{make(chan string),cliAddr,cliAddr}
//放到map中
onlineMap[cliAddr] = cli
//新开一个协程,专门用来发送信息给当前的客户端,这里主要一有消息就开始消费
go WriteMsgToClient(cli,conn)
//这里就往message发送信息了,Manager()方法开始向客户端发送消息了
message <- "[" + cli.Addr + "]" + cli.Name + ":login"
//提示我是谁
cli.C <- "[" + cli.Addr + "]" + cli.Name + ":" + "i am here"
isQuit := make(chan bool)
hasData := make(chan bool)
//读取客户端发来的数据
go func() {
b1 := make([]byte,1024)
for {
n1,e1 := conn.Read(b1)
if n1 == 0 {
isQuit <- true
fmt.Println("conn.Read err = ", e1)
return
}
m1 := string(b1[:n1 - 1])
if "who" == m1 {
conn.Write([]byte("user list : \n"))
for _,tmp := range onlineMap {
msg := tmp.Addr + ":" + tmp.Name + "\n"
conn.Write([]byte(msg))
}
}else if len(m1) >= 8 && m1[:6] == "rename" {
name := strings.Split(m1,"|")[1]
cli.Name = name
onlineMap[cliAddr] = cli
conn.Write([]byte("rename success!\n"))
}else {
message <- "[" + cli.Addr + "]" + cli.Name + ":" + string(b1[:n1 - 1])
}
hasData <- true
}
}()
for {
select {
case <- isQuit:
delete(onlineMap,cliAddr)
message <- "[" + cli.Addr + "]" + cli.Name + ":" + "login out!"
return
case <- hasData:
case <- time.After(30 * time.Second):
delete(onlineMap,cliAddr)
message <- "[" + cli.Addr + "]" + cli.Name + ":" + "time out leave out!"
return
}
}
}
func WriteMsgToClient(cli Client, conn net.Conn) {
for mse := range cli.C {
conn.Write([]byte(mse + "\n"))
}
}
用Go语言写的一个多人聊天室
最新推荐文章于 2022-04-23 10:40:07 发布