package main
import ( "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)) }
}
|
请发表评论