0

我正在尝试在 Go 中进行简单的控制台聊天,只是为了练习。但是,我不知道如何从服务器发回消息。服务器只是收到一条消息,然后关闭连接。我该如何发送回复?

我一直在搜索并找到有关 websockets 的信息,但我认为它们用于与浏览器交互。

这是服务器的两个功能:

func runServer() {
    // Listen on a port
    listen, error := net.Listen("tcp", ":8272")

    // Handles eventual errors
    if error != nil {
        fmt.Println(error)
        return
    }

    fmt.Println("Listening in port 8272.")

    for {
        // Accepts connections
        con, error := listen.Accept()

        // Handles eventual errors
        if error != nil {
            fmt.Println(error)
            continue
        }

        fmt.Println("Connection accepted.")

        // Handles the connection
        go handleConnection(con)
    }
}

func handleConnection(con net.Conn) {
    fmt.Println("Handling connection.")

    var message string

    // Decodes the received message
    decoder := gob.NewDecoder(con)
    error := decoder.Decode(&message)

    // Checks for errors
    if error != nil {
        fmt.Println(error)
    } else {
        fmt.Println("Received", message)
    }

    // Closes the connection
    con.Close()
    fmt.Println("Connection closed.")
}

这是客户端的功能:

func runClient() {
    // Connects to server
    con, error := net.Dial("tcp", "127.0.0.1:8272")

    // Handles eventual errors
    if error != nil {
        fmt.Println(error)
        return
    }

    fmt.Println("Connected to 127.0.0.1:8272.")

    // Sends a message
    message := "Hello world"
    encoder := gob.NewEncoder(con)
    error = encoder.Encode(message)

    // Checks for errors
    if error != nil {
        fmt.Println(error)
    }

    con.Close()

    fmt.Println("Message sent. Connection closed.")
}

提前致谢。

4

1 回答 1

4

您的con对象是一个连接,它具有此处描述ReadWrite方法:here。您应该循环连接,尝试Read传入数据,然后处理它并(可能)Write返回服务器响应。(这里,bufferiopackage之类的可以帮你更方便的处理,这只是底层ReadWriter接口)

该文档显示了一个小示例

go func(c net.Conn) {
    // Echo all incoming data.
    io.Copy(c, c)
    // Shut down the connection.
    c.Close()
}(conn)

仅处理第一条消息然后关闭。您可以像这样处理每条传入的消息:

go func(c net.Conn) {
    // Infinite loop: Get data, copy them and start over
    for {
        // Echo all incoming data.
        io.Copy(c, c)
    }
    // Shut down the connection.
    c.Close()
}(conn)

当然,替换io.Copy为与您的服务器相关的任何内容,因此您的示例将是这样的:

func handleConnection(con net.Conn) {
    fmt.Println("Handling connection.")

    defer func() {
        // Closes the connection
        con.Close()
        fmt.Println("Connection closed.")
    }()

    var message string

    // Decodes the received message
    decoder := gob.NewDecoder(con)
    encoder := gob.NewEncoder(con)
    for {
        error := decoder.Decode(&message)

        // Checks for errors
        if error != nil {
            fmt.Println(error)
            // Exit the loop
            return
        } else {
            fmt.Println("Received", message)
            // Sending back
            if error = encoder.Encode(message); error != nil {
                 fmt.Println(error)
                 return
            } else {
                fmt.Println("Echo'd successfuly ! Waiting for next message...")
            }
        }
    }
}

此外,您可能应该使用包log而不是fmt日志消息(但这在这里无关紧要)。

了解它是如何工作的一个好地方是在这里http浏览默认服务器的实现。

同样,您的客户端应该使用相同的模式循环:

LOOP:
    Send data (e.g. encoder.Encode)
    Receive data (e.g. decoder.Decode)
    if problem or termination -> break out of loop
END
close connection
于 2013-08-14T13:06:04.623 回答