package main
import (
"fmt"
"net"
)
type client struct {
name string
addr string
C chan string
}
func writemsg2client(clinet client,conn net.Conn) {
for m := range clinet.C {
conn.Write([]byte(m + "\n"))
}
}
func makemsg(name string, addr string, s string) string {
return "[" + addr + "]" + name + " " + s
}
//每一个进入聊天室的用户都将启动一个handleconn的go程来处理事件
func handleconn(conn net.Conn) {
defer conn.Close()
addr := conn.RemoteAddr().String()
fmt.Printf("用户 %s 进入了房间\n", addr)
client := client{addr, addr, make(chan string)}
go writemsg2client(client,conn)
onlinemap[addr] = client
//登录进来一切准备就绪后就给所有人广播上线信息啦
Message <- makemsg(client.name, addr, " 进入了房间")
var ifquit=make(chan bool)
//从这单独开启一个go程来读取用户输入的信息
go func() {
buf:=make([]byte,4096)
for {
n,_:=conn.Read(buf)
if n==0 {
fmt.Printf("%s离开了房间\n",client.name)
ifquit<-true
return
}
Message<-makemsg(client.name,addr,string(buf[:n-1]))
}
}()
for {
select {
case <-ifquit:
//退出处理
delete(onlinemap,addr)
Message<-makemsg(client.name,addr,"out time to leave")
close(client.C)
return
}
}
}
var Message = make(chan string)
var onlinemap map[string]client = make(map[string]client)
//主函数
func main() {
listener, _ := net.Listen("tcp", "127.0.0.1:8888")
defer listener.Close()
//提前开启全局Message的go程,防止被阻塞
go Manager()
for {
conn, err := listener.Accept()
if err != nil {
fmt.Println("accept err", err)
continue
}
//每一个连接进来的用户都会被分配进入一个子go程,用来处理上面我们提到的各种功能
go handleconn(conn)
}
}
func Manager() {
for {
msg := <-Message
fmt.Println(msg)
for _, s := range onlinemap {
s.C <- msg
}
}
}
https://blog.csdn.net/weixin_42940826/article/details/82386275
原文:https://www.cnblogs.com/brady-wang/p/15090119.html