登录
首页 >  Golang >  Go问答

改为:为何 net.Conn.close() 在不恰当的时机关闭?

来源:stackoverflow

时间:2024-03-18 19:18:36 333浏览 收藏

**为什么 net.Conn.close() 在不恰当时机关闭?** 在使用 Go 语言编写 TCP 客户端程序时,开发者可能遇到 net.Conn.close() 在不恰当的时机关闭连接的问题。这会导致客户端无法与服务器通信,即使程序仍在运行。 问题的原因在于 Go 语言中的 goroutine 是异步执行的。在主函数中调用 go handleconn(conn) 后,主函数继续执行并关闭连接,而 handleconn 函数仍在后台运行。因此,在 handleconn 函数完成其工作之前,连接就被关闭了。 为了解决这个问题,开发者需要将 conn.close() 调用移到 handleconn 函数内,确保在 handleconn 函数完成其工作后才关闭连接。此外,开发者还可以通过使用通道或其他同步机制来确保主函数在 handleconn 函数完成工作之前不会继续执行。

问题内容

我正在尝试从 tcp 客户端读取和写入一些命令。我想在执行最后一个函数后关闭连接,但由于某种原因,即使在之后显式放置,服务器似乎也会在函数中间断开连接。

package main
    
    import (
        "bufio"
        "fmt"
        "io"
        "log"
        "net"
        "strconv"
        "strings"
        "time"
    )
    
    
    
    func main() {
        listener, err := net.listen("tcp", "localhost:8000")
        if err != nil {
            log.fatal(err)
        }
        for {
            conn, err := listener.accept()
            if err != nil {
                log.print(err)
            }
            go handleconn(conn)
            conn.close()
        }
    
    }
    
    func handleconn(someconnection net.conn) {
        func1(someconnection)
        func2(someconnection) //connection drops in the middle of executing this part
    }
func func2(someconnection net.conn) {

    //send message(a string)
    _, err := io.writestring(someconnection, dosomething)
    if err != nil {
        log.fatal(err)
    }
    //await reply
    //send another message
    _, err = io.writestring(someconnection, dosomething)
    if err != nil {
        log.fatal(err)
    }
   //await reply

    //send another message, connection tends to close somewhere here
    _, err = io.writestring(someconnection, dosomething)
    if err != nil {
        log.fatal(err)
    }

    //await,send
    _, err = io.writestring(someconnection, do something)
    if err != nil {
        log.fatal(err)
    }

    //await, read and print message
    c := bufio.newreader(someconnection)
    buff1 := make([]byte, maxclientmessagelength)
    buff1, err = c.readbytes(delimiter)

    fmt.printf("\n%s\n", buff1)

    _, err = io.writestring(someconnection, dosomething)
    if err != nil {
        log.fatal(err)
    }
}

这意味着试图向后通信的客户端根本无法通信,但程序会运行到最后。

更新 1:

通过将延迟关闭语句放置在首次获取连接时取得了一些进展。

func main() {
listener, err := net.Listen("tcp", "localhost:8000")
if err != nil {
    log.Fatal(err)
}
for {
    conn, err := listener.Accept()
    if err != nil {
        log.Print(err)
    }
    defer conn.Close()
    go handleConn(conn)
}}

现在它不一定会在我希望它关闭的那一秒内关闭,但至少现在它会一直运行。


正确答案


goroutines 是异步的,因此在此处调用 handleconn 后:

go handleconn(conn)
conn.close()

main函数继续执行并关闭连接。 尝试定期调用handleconn函数(不使用go)。

conn.close需要在handleconn完成其工作后完成。您可以使用通道与主线程进行通信,但这会太复杂(并且还会阻止主线程的执行)。应该这样做

func main() {
    listener, err := net.listen("tcp", "localhost:8000")
    if err != nil {
        log.fatal(err)
    }
    for {
        conn, err := listener.accept()
        if err != nil {
            log.print(err)
        }
        go handleconn(conn)
        // remove below line
        // conn.close()
    }
}

handleconn内添加conn.close

func handleConn(someconnection net.Conn) {
    // ADD BELOW LINE
    defer someconnection.Close()
    func1(someconnection)
    func2(someconnection)
}

这确保 conn.closefunc1func2 执行完毕后被调用

今天关于《改为:为何 net.Conn.close() 在不恰当的时机关闭?》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>