美文网首页
19年第35周:Go语言 搭建聊天服务器

19年第35周:Go语言 搭建聊天服务器

作者: 习惯研究所所长 | 来源:发表于2019-10-07 17:05 被阅读0次

    一、聊天服务器结构图

    尬聊服务器

    二、效果演示

    聊天服务器.gif

    三、程序代码

    • 服务端.go
    // 广播器的编写
    
    type client  chan<- string // chan<- 只能发送
    
    var (
        entering = make(chan client) // 在线的客户端
        leaving = make(chan client) // 离线的客户端
        messages = make(chan string) // 所有接收到的客户消息
    )
    
    func broadcaster(){
        clients := make(map[client]bool) // 所有连接的客户端
        for {
            select {
                // 1, 消息广播给所有的客户端
                case msg := <- messages:
                    for cli := range clients {
                        cli <- msg // 把消息传给每个客户端(TCP连接通道)
                    }
                // 2, 注册用户
                case cli := <-entering:
                    clients[cli] = true  // 上线了
                // 3, 注销用户
                case cli := <-leaving:
                    delete(clients, cli) // 删除
                    close(cli) // 关闭这个通道
            }
        }
    
    }
    
    // 处理请求的编写
    
    func handleChatConn(conn net.Conn){
        // 对外发送客户消息的通道
        clientCh := make(chan string)
        go clientWriter(conn, clientCh)
    
        // 获取客户端的地址,作为用户的区分,知道谁是谁的谁
        who := conn.RemoteAddr().String()  // T
        // 每一个新用户(新的TCP连接),发送一条who信息给广播
        clientCh <- "你是" + who
        messages <- who + "上线!"
        entering <- clientCh  // 注册新用户(新建的TCP连接)
    
        input := bufio.NewScanner(conn)
        for input.Scan() {
            // 阻塞读取信息,并将信息写入Socket缓冲区
            messages <- who + ": " + input.Text()
        }
    
        // 对话框关闭后代表客户端退出
        leaving <- clientCh // 注销用户
        messages <- who + " 下线!"
        conn.Close()
    }
    
    // 对客户端Tcp通道写入的编写
    func clientWriter(conn net.Conn, ch <- chan string) {
        for msg := range ch {
            // 每当从客户端通道读取到信息,都转写入conn中
            // 客户端TCP信息是由广播器写入的
            fmt.Fprintln(conn, msg)
        }
    }
    
    • 客户端.go
    
    // 聊天服务的客户端编写
    func ChatClient(){
        conn, err := net.Dial("tcp", "localhost:8000")
        if err!=nil {
            log.Fatal(err)
        }
        done := make(chan struct{})
        go func(){
            io.Copy(os.Stdout, conn)  // 读取客户端的信息到标准输出
            log.Println("Done")
            done <- struct{}{}
        }()
    
        mustCopy(conn, os.Stdin) // 读取标准输入到tcp通道
        conn.Close()
        <-done // 丢弃
    }
    
    
    func mustCopy(dst io.Writer, src io.Reader) {
        _,err := io.Copy(dst, src)
        if err != nil {
            log.Fatal(err)
        }
    }
    
    

    欢迎交流!

    相关文章

      网友评论

          本文标题:19年第35周:Go语言 搭建聊天服务器

          本文链接:https://www.haomeiwen.com/subject/wvoaectx.html