• 多人聊天室


    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)
        }
    }




  • 相关阅读:
    Go:获取命令行参数
    Go:文件操作
    Go:类型断言
    GO:interface
    Go:面向"对象"
    Go:工厂模式
    layui中流加载layui.flow
    js显示当前时间
    layui中的分页laypage
    layui中的多图上传
  • 原文地址:https://www.cnblogs.com/hualou/p/12069706.html
Copyright © 2020-2023  润新知