package main

    import (

    1. "fmt"
    2. "net"
    3. "strings"
    4. "time"

    )

    type User struct {

    1. id string
    2. name string
    3. msg chan string

    }

    //搞一个key-value变量(map结构),并make出来空间

    var allUsers = make(map[string]User)

    //全局管道,进行广播

    var message = make(chan string, 10)

    func main() {

    1. listener, err := net.Listen("tcp", "172.16.76.129:8080")
    2. if err != nil {
    3. fmt.Println("服务器端提示:listen err:", err)
    4. return
    5. }
    6. //监听广播管道
    7. go broadcast()
    8. //持续监听新用户连接请求
    9. for {
    10. fmt.Println("服务器端提示:监听中...")
    11. conn, err := listener.Accept()
    12. if err != nil {
    13. fmt.Println("conn err:", err)
    14. }
    15. fmt.Println("服务器端提示:建立连接成功...")
    16. //握手成功
    17. go handler(conn)
    18. }

    }

    //连接完成,处理业务

    func handler(conn net.Conn) {

    1. fmt.Println("服务器端提示:handle...")
    2. //把所有user写进map
    3. clientAddr := conn.RemoteAddr().String()
    4. newuser := User{
    5. id: clientAddr,
    6. name: clientAddr,
    7. msg: make(chan string),
    8. }
    9. allUsers[newuser.id] = newuser
    10. //写回客户端
    11. go writebackToClient(&newuser, conn)
    12. //退出账户
    13. var isQuit = make(chan bool)
    14. var timeReset = make(chan bool)
    15. go quit(isQuit, timeReset, &newuser, conn)
    16. //上线广播
    17. msginfo := fmt.Sprintf("id:%s,name:%s 上线了...\n", newuser.id, newuser.name)
    18. message <- msginfo
    19. //---------- 处理具体业务 ------------
    20. //持续接收客户端数据
    21. for {
    22. buf := make([]byte, 1024)
    23. //读取客户端数据到buf
    24. count, err := conn.Read(buf)
    25. //用户crtl+c退出
    26. if count == 0 {
    27. isQuit <- true
    28. return
    29. }
    30. if err != nil {
    31. fmt.Printf("服务器端提示:conn.Read err:%s,count:%d", err, count)
    32. return
    33. }
    34. //所有用户信息整理成一个字符串,并用回车换行
    35. var whoUser []string
    36. for _, user := range allUsers {
    37. userinfo := fmt.Sprintf("id:%s,name:%s", user.id, user.name)
    38. whoUser = append(whoUser, userinfo)
    39. }
    40. r := strings.Join(whoUser, "\n")
    41. //查询所有用户业务
    42. userInput := string(buf[:count-1])
    43. if len(userInput) == 5 && (userInput == "[who]" || userInput == "[WHO]") {
    44. newuser.msg <- (r + "\n")
    45. //修改名字
    46. } else if len(userInput) > 8 && (userInput[:8] == "[rename]") {
    47. newuser.name = strings.Split(userInput, "]")[1]
    48. allUsers[newuser.id] = newuser
    49. newuser.msg <- "[rename] successfully!\n"
    50. } else {
    51. message <- (userInput + "\n")
    52. }
    53. //重置计时器
    54. timeReset <- true
    55. }
    56. //---------- 处理具体业务 ------------

    }

    //广播消息

    func broadcast() {

    1. fmt.Println("服务器端提示:广播启动成功...")
    2. defer fmt.Println("服务器端提示:广播异常退出...")
    3. for {
    4. info := <-message
    5. for _, user := range allUsers {
    6. user.msg <- info
    7. }
    8. }

    }

    //写回客户端

    func writebackToClient(user *User, conn net.Conn) {

    1. fmt.Println("服务器端提示:writebackToClient启动...")
    2. for {
    3. data := <-user.msg //必须加上 <-
    4. conn.Write([]byte(data))
    5. }
    6. // for data := range user.msg { //range下不用 <-
    7. // conn.Write([]byte(data))
    8. // }

    }

    //退出账户

    func quit(isQuit, timeReset <-chan bool, user *User, conn net.Conn) {

    1. fmt.Println("服务器端提示:等待执行退出账户...")
    2. defer fmt.Println("服务器端提示:用户退出成功!")
    3. // if <-isQuit {
    4. // message <- fmt.Sprintf("username:%s退出\n", user.name)
    5. // delete(allUsers, user.id)
    6. // conn.Close()
    7. // return
    8. // }
    9. for {
    10. select {
    11. case <-isQuit:
    12. message <- fmt.Sprintf("username:%s主动退出", user.name)
    13. delete(allUsers, user.id)
    14. conn.Close()
    15. return
    16. case <-time.After(10 * time.Second):
    17. message <- fmt.Sprintf("username:%s超时退出", user.name)
    18. delete(allUsers, user.id)
    19. conn.Close()
    20. return
    21. case <-timeReset:
    22. fmt.Printf("客户端提示:uesrname:%s重置计时器成功\n", user.name)
    23. }
    24. }

    }