Goチャットルーム(goroutine)


前言
無名先生のgoroutineとchannelについての説明授業を見て、よく分からなかったので、チャットルームの機能を実現することにしました.
どうしてグループチャットなの?
グループチャットは論理的に簡単だから
注:本栗はgoroutineにしか使われておらずchannelには使われていません
概要
1.チャットルームの構成
チャットルームは2つの部分に分かれています.それぞれ:
  • サービス側
  • クライアント
  • そして、一般的にはお互いにチャットしているのはクライアントだけで、サービス側はスケジューリングの役割を果たしているだけです.
    2.情報の送受信の流れ (S) (C1) (C2) (C3)SはC 1 C 2 C 3と接続されている
    理論上の流れはこうです.
  • C 1はSにメッセージを送信
  • S受信情報
  • S受信した情報をC 2 C 3
  • にブロードキャストする
  • C 2 C 3受信情報
  • じっこう
    1.サービス側
    1)コード
    package main
    
    import (
        "time"
        "fmt"
        "net"
    )
    
    //     map 
    var client_map =  make(map[string]*net.TCPConn)
    
    //     
    func listen_client(ip_port string) {
        tcpAddr, _ := net.ResolveTCPAddr("tcp", ip_port)
        tcpListener, _ := net.ListenTCP("tcp", tcpAddr)
        for {//      
            client_con, _ := tcpListener.AcceptTCP()//       
            client_map[client_con.RemoteAddr().String()] = client_con//        map
            go add_receiver(client_con)
            fmt.Println("   : ", client_con.RemoteAddr().String(), "    .")
        }
    }
    
    //         
    func add_receiver(current_connect *net.TCPConn) {
        for {
            byte_msg := make([]byte, 2048)
            len, err := current_connect.Read(byte_msg)
            if err != nil { current_connect.Close() }
            fmt.Println(string(byte_msg[:len]))
            msg_broadcast(byte_msg[:len], current_connect.RemoteAddr().String())
        }
    }
    
    //       client
    func msg_broadcast(byte_msg []byte, key string) {
        for k, con := range client_map {
            if k != key { con.Write(byte_msg) }
        }
    }
    
    //    
    func main() {
        fmt.Println("     ...")
        time.Sleep(1 * time.Second)
        fmt.Println("         ...")
        go listen_client("127.0.0.1:1801")
        select{}
    }    
    

    b)説明
    main関数を除いて、2つのroutineがあります.それぞれ:
  • 傍受接続
  • 受信メッセージ(ブロードキャストメッセージもここにある)
  • 2.クライアント
    a)コード
    package main
    
    import (
        "fmt"
        "net"
        "os"
        "bufio"
    )
    
    //    
    var login_name string
    
    //     
    var self_connect *net.TCPConn
    
    //      
    var reader = bufio.NewReader(os.Stdin)
    
    //     
    func connect(addr string) {
        tcp_addr, _ := net.ResolveTCPAddr("tcp", addr) //   tcp
        con, err := net.DialTCP("tcp", nil, tcp_addr) //   
        self_connect = con
        if err != nil {
            fmt.Println("       ")
            os.Exit(1)
        }
        go msg_sender()
        go msg_receiver()
    }
    
    //      
    func msg_receiver() {
        buff := make([]byte, 2048)
        for {
            len, _ := self_connect.Read(buff) //     
            fmt.Println(string(buff[:len]))
        }
    }
    
    //      
    func msg_sender() {
        for {
            read_line_msg, _, _ := reader.ReadLine()
            read_line_msg = []byte(login_name + " : " + string(read_line_msg))
            self_connect.Write(read_line_msg)
        }
    }
    
    //    
    func main() {
        fmt.Println("       ?")
        name, _, _ := reader.ReadLine()
        login_name = string(name)
        connect("127.0.0.1:1801")
        select{}
    }
    

    b)説明
    同様に、クライアントにも2つのroutineがあります.
  • メッセージ受信機
  • メッセージ送信機
  • プライマリ・スレッドでの接続の確立
    3.効果図
    a)サービス側
    b)クライアント_1
    c)クライアント_2
    の最後の部分
    ここではチャンネルは使われていません
    小栗は経験をまとめ、交流を学ぶためだけに覚えています.