多人聊天室

package main

import (
    "fmt"
    "net"
    "strings"
    "time"
)

type Client struct {
    C    chan string
    Name string
    Addr string
}

//创建全局map,存储在现空间
var onlineMap map[string]Client

//创建全局channel传递用户信息
var message = make(chan string)

func WriteMsgToClient(clnt Client, conn net.Conn) {
    //监听用户自带channel中的数据
    for msg := range clnt.C {
        fmt.Println(msg)
        conn.Write([]byte(msg + "
"))
    }
}
func MakeMsg(clnt Client, msg string) string {
    buf := "[" + clnt.Addr + "]" + clnt.Name + ": " + msg
    return buf
}

func manager() {
    //监听全局channel中是否有数据,存储至msg,无数据阻塞
    for {
        msg := <-message
        for _, clnt := range onlineMap {
            clnt.C <- msg
        }
    }
}

func HandlerConnect(conn net.Conn) {
    defer conn.Close()
    addr := conn.RemoteAddr().String()
    clnt := Client{make(chan string), addr, addr}
    //将信连接用户,添加到在线用户map中
    onlineMap[addr] = clnt
    //创建专门用来给当前用户发送消息的go程
    go WriteMsgToClient(clnt, conn)
    isQuit := make(chan bool)
    //发送用户上线消息到全局channel中
    message <- MakeMsg(clnt, "login")
    hasData := make(chan bool)
    //创建一个匿名go程,专门处理用户发送的消息
    go func() {
        buf := make([]byte, 4096)
        for {
            n, err := conn.Read(buf)
            if n == 0 {
                isQuit <- true
                return
            }
            if err != nil {
                fmt.Println("conn.Read err:", err)
                return
            }
            //将读到的用户消息,写入到message中
            msg := string(buf[:n-1])
            if msg == "who" && len(msg) == 3 {
                conn.Write([]byte("online user list:
"))
                for _, user := range onlineMap {
                    userInfo := user.Addr + ":" + user.Name + "
"
                    conn.Write([]byte(userInfo))
                }
            } else if len(msg) >= 8 && strings.HasPrefix(msg, "rename|") {
                newName := strings.Split(msg, "|")[1]
                for ip, user := range onlineMap {
                    if ip == addr {
                        continue
                    }
                    if newName == user.Name {
                        conn.Write([]byte("username exists
"))
                    } else {
                        clnt.Name = newName
                        onlineMap[addr] = clnt
                        conn.Write([]byte("rename successfully
"))
                    }
                }
            } else {
                message <- MakeMsg(clnt, msg)
            }
            hasData <- true

        }
    }()
    for {
        select {
        case <-isQuit:
            close(clnt.C) //关闭clnt.c让子协程退出,因为协程退出,子协程不会退出
            delete(onlineMap, clnt.Addr)
            message <- MakeMsg(clnt, "logout")
            return
        case <-time.After(time.Second * 10):
            close(clnt.C)
            delete(onlineMap, clnt.Addr)
            message <- MakeMsg(clnt, "logout")
            return
        case <-hasData:

        }

    }
}

func main() {
    //创建监听套接字
    onlineMap = make(map[string]Client)
    listener, err := net.Listen("tcp", "127.0.0.1:8000")
    if err != nil {
        fmt.Println("Listen err", err)
        return
    }
    defer listener.Close()
    go manager()
    for {
        conn, err := listener.Accept()
        if err != nil {
            fmt.Println("Accept Err", err)
            return
        }
        go HandlerConnect(conn)
    }
}




原文地址:https://www.cnblogs.com/hualou/p/12069706.html