首页 > 解决方案 > 如何编写在 goroutines 中执行的函数来发送和接收消息?

问题描述

我必须编写一个客户端代码,它以字符串的形式从服务器接收消息,并从控制台获取输入以结束消息到服务器。这两个操作应该彼此同时运行。我编写了一个代码来执行这些操作,但不是同时执行。

这是我当前的代码的样子:

func SocketClient() {
    conn, err := net.Dial("tcp", ":9000")
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    server_reader := bufio.NewReader(conn)
    input_reader := bufio.NewReader(os.Stdin)
    for {
        // for sending messages
        buff, err := input_reader.ReadString('\n')
        if err != nil {
            log.Fatalln(err)
        }
        conn.Write([]byte(buff))

        // for receiving messages but this won't run until the above has taken input from console
        buff2, err := server_reader.ReadString('\n')
        if err != nil {
            log.Fatalln(err)
        }
        fmt.Println("Received: %s", buff2)
    }
}

buff 接收来自服务器的传入消息,然后 buff2 从控制台接收传出消息输入,但为了再次接收传入消息,buff2 需要一些输入。我知道这可以使用通道、互斥锁等来完成,但是由于我对基础知识缺乏了解,我在使用它们时遇到了问题。

我想实际的代码应该是这样的:

func SocketClient() {
    conn, err := net.Dial("tcp", ":9000")
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    go func() {
        // for sending messages
    } ()
    go func() {
        // for receiving messages
    } ()
}

如何将输入和输出作为两个独立的 goroutine?

标签: gonetworkingtcpwebsocketserver

解决方案


直接在 中运行其中一个循环SocketClient。在由SocketClient.

func SocketClient() error {
    conn, err := net.Dial("tcp", ":9000")
    if err != nil {
        return err
    }
    defer conn.Close()
    server_reader := bufio.NewReader(conn)
    input_reader := bufio.NewReader(os.Stdin)

    go func() {
        defer conn.Close()

        // This loop will break and the goroutine will exit when the
        // SocketClient function executes conn.Close().

        for {
            buff, err := server_reader.ReadBytes('\n')
            if err != nil {
                // optional: log.Fatal(err) to cause program to exit without waiting for new input from stdin.
                return
            }
            fmt.Printf("Received: %s", buff)
        }
    }()

    for {
        // for sending messages
        buff, err := input_reader.ReadBytes('\n')
        if err != nil {
            return err
        }
        if _, err := conn.Write(buff); err != nil {
            return err
        }
    }
}

使用 bufio.ReaderReadBytes方法而不是ReadString避免[]byte和之间不必要的转换string


推荐阅读