package main
import (
"fmt""net""strings""time")
type User struct {
id stringname stringmsg chan string}
//搞一个key-value变量(map结构),并make出来空间
var allUsers = make(map[string]User)
//全局管道,进行广播
var message = make(chan string, 10)
func main() {
listener, err := net.Listen("tcp", "172.16.76.129:8080")if err != nil {fmt.Println("服务器端提示:listen err:", err)return}//监听广播管道go broadcast()//持续监听新用户连接请求for {fmt.Println("服务器端提示:监听中...")conn, err := listener.Accept()if err != nil {fmt.Println("conn err:", err)}fmt.Println("服务器端提示:建立连接成功...")//握手成功go handler(conn)}}
//连接完成,处理业务
func handler(conn net.Conn) {
fmt.Println("服务器端提示:handle...")//把所有user写进mapclientAddr := conn.RemoteAddr().String()newuser := User{id: clientAddr,name: clientAddr,msg: make(chan string),}allUsers[newuser.id] = newuser//写回客户端go writebackToClient(&newuser, conn)//退出账户var isQuit = make(chan bool)var timeReset = make(chan bool)go quit(isQuit, timeReset, &newuser, conn)//上线广播msginfo := fmt.Sprintf("id:%s,name:%s 上线了...\n", newuser.id, newuser.name)message <- msginfo//---------- 处理具体业务 ------------//持续接收客户端数据for {buf := make([]byte, 1024)//读取客户端数据到bufcount, err := conn.Read(buf)//用户crtl+c退出if count == 0 {isQuit <- truereturn}if err != nil {fmt.Printf("服务器端提示:conn.Read err:%s,count:%d", err, count)return}//所有用户信息整理成一个字符串,并用回车换行var whoUser []stringfor _, user := range allUsers {userinfo := fmt.Sprintf("id:%s,name:%s", user.id, user.name)whoUser = append(whoUser, userinfo)}r := strings.Join(whoUser, "\n")//查询所有用户业务userInput := string(buf[:count-1])if len(userInput) == 5 && (userInput == "[who]" || userInput == "[WHO]") {newuser.msg <- (r + "\n")//修改名字} else if len(userInput) > 8 && (userInput[:8] == "[rename]") {newuser.name = strings.Split(userInput, "]")[1]allUsers[newuser.id] = newusernewuser.msg <- "[rename] successfully!\n"} else {message <- (userInput + "\n")}//重置计时器timeReset <- true}//---------- 处理具体业务 ------------}
//广播消息
func broadcast() {
fmt.Println("服务器端提示:广播启动成功...")defer fmt.Println("服务器端提示:广播异常退出...")for {info := <-messagefor _, user := range allUsers {user.msg <- info}}}
//写回客户端
func writebackToClient(user *User, conn net.Conn) {
fmt.Println("服务器端提示:writebackToClient启动...")for {data := <-user.msg //必须加上 <-conn.Write([]byte(data))}// for data := range user.msg { //range下不用 <-// conn.Write([]byte(data))// }}
//退出账户
func quit(isQuit, timeReset <-chan bool, user *User, conn net.Conn) {
fmt.Println("服务器端提示:等待执行退出账户...")defer fmt.Println("服务器端提示:用户退出成功!")// if <-isQuit {// message <- fmt.Sprintf("username:%s退出\n", user.name)// delete(allUsers, user.id)// conn.Close()// return// }for {select {case <-isQuit:message <- fmt.Sprintf("username:%s主动退出", user.name)delete(allUsers, user.id)conn.Close()returncase <-time.After(10 * time.Second):message <- fmt.Sprintf("username:%s超时退出", user.name)delete(allUsers, user.id)conn.Close()returncase <-timeReset:fmt.Printf("客户端提示:uesrname:%s重置计时器成功\n", user.name)}}}
