美文网首页
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