19年第35周:Go語言 搭建聊天服務(wù)器

一、聊天服務(wù)器結(jié)構(gòu)圖

尬聊服務(wù)器

二、效果演示

聊天服務(wù)器.gif

三、程序代碼

  • 服務(wù)端.go
// 廣播器的編寫

type client  chan<- string // chan<- 只能發(fā)送

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) // 關(guān)閉這個通道
        }
    }

}

// 處理請求的編寫

func handleChatConn(conn net.Conn){
    // 對外發(fā)送客戶消息的通道
    clientCh := make(chan string)
    go clientWriter(conn, clientCh)

    // 獲取客戶端的地址,作為用戶的區(qū)分,知道誰是誰的誰
    who := conn.RemoteAddr().String()  // T
    // 每一個新用戶(新的TCP連接),發(fā)送一條who信息給廣播
    clientCh <- "你是" + who
    messages <- who + "上線!"
    entering <- clientCh  // 注冊新用戶(新建的TCP連接)

    input := bufio.NewScanner(conn)
    for input.Scan() {
        // 阻塞讀取信息,并將信息寫入Socket緩沖區(qū)
        messages <- who + ": " + input.Text()
    }

    // 對話框關(guān)閉后代表客戶端退出
    leaving <- clientCh // 注銷用戶
    messages <- who + " 下線!"
    conn.Close()
}

// 對客戶端Tcp通道寫入的編寫
func clientWriter(conn net.Conn, ch <- chan string) {
    for msg := range ch {
        // 每當(dāng)從客戶端通道讀取到信息,都轉(zhuǎn)寫入conn中
        // 客戶端TCP信息是由廣播器寫入的
        fmt.Fprintln(conn, msg)
    }
}
  • 客戶端.go

// 聊天服務(wù)的客戶端編寫
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)  // 讀取客戶端的信息到標(biāo)準(zhǔn)輸出
        log.Println("Done")
        done <- struct{}{}
    }()

    mustCopy(conn, os.Stdin) // 讀取標(biāo)準(zhǔn)輸入到tcp通道
    conn.Close()
    <-done // 丟棄
}


func mustCopy(dst io.Writer, src io.Reader) {
    _,err := io.Copy(dst, src)
    if err != nil {
        log.Fatal(err)
    }
}

歡迎交流!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 古風(fēng) 詠老爺車 溫志齡 多種老車蘊(yùn)赤縣,卅秋尋蹤修復(fù)原。 爛鐵破銅變活寶,厚重文化建博館。 注:重慶沙坪壩區(qū)歌樂...
    碧野牧歌閱讀 215評論 0 0
  • https://segmentfault.com/q/1010000009543764 video fixed布局...
    xmb閱讀 537評論 0 1
  • 好好睡一會吧 人生缺的就是睡眠 不知道怎么回事 我第一次提這樣的問題 你居然第一反應(yīng)是對T3 我覺得真是無法猜測 ...
    一泓秋水長天閱讀 92評論 0 2

友情鏈接更多精彩內(nèi)容