package mainimport ( "fmt" "net" "time")type Client struct { ch chan string //用戶發送數據的管道 name string //用戶名 addr string//網絡地址} var message = make(chan string) //用來保存用戶的消息//定義一個map 值爲在線的用戶var onlineClientMap map[string]Client//func main() { listener,err := net.Listen("tcp","127.0.0.1:8000") if err !=nil{ fmt.Println(err) } defer listener.Close() go Manager() //主協程,循環阻塞用戶鏈接 for{ conn, err := listener.Accept() if err!=nil{ fmt.Println(err) continue } go handleConn(conn) }}func makeMsg(client Client,msg string)(buff string){ buff ="["+client.addr+"]"+client.name+":"+msg+"\n" return}func handleConn(conn net.Conn){ cliAddr:= conn.RemoteAddr().String() defer conn.Close() client :=Client{ make(chan string), cliAddr, cliAddr, } onlineClientMap[cliAddr] = client //給當前客戶端發送信息 go writeMsgToClient(client,conn) //廣播某個在線 message<-"I am here\n" message<- makeMsg(client,"login") //是否主動退出 isQuit:=make(chan bool) hasData:= make(chan bool) //新開一個協程接收用戶發過來的數據 go func() { buff:= make([]byte,2048) for{ n,err :=conn.Read(buff) fmt.Println(n) if err!=nil{ fmt.Println(nil) } if n==0{ fmt.Println("斷開鏈接") isQuit<-true return } msg := string(buff[:n-1]) if len(msg)==3&& msg =="who"{ for _,tmp := range onlineClientMap{ msg = tmp.addr+":"+tmp.name+"\n" conn.Write([]byte(msg)) } }else{ message<-makeMsg(client,msg) } hasData<-true } }() for{ select { case <-isQuit: delete(onlineClientMap,cliAddr)//當前用戶從map移除 message<-makeMsg(client,"login out")//廣播退出 return case <-hasData: case <-time.After(60*time.Second): delete(onlineClientMap,cliAddr)//當前用戶從map移除 message<-makeMsg(client,"time out")//廣播退出 return } }}func Manager() { onlineClientMap = make(map[string]Client)//給map分配空間 for{ msg := <-message for _ ,client :=range onlineClientMap{ client.ch<-msg } }}func writeMsgToClient(client Client,conn net.Conn) { for msg:= range client.ch{ conn.Write([]byte(msg)) }}