这段代码中的 TCP 连接何时关闭?

When the TCP connection close in this code?

当我读到这篇文章时opensource code.

关于这两个函数我有两个问题:

func listenTCP() {
    for {
        conn, err := tcpListener.Accept()
        if err != nil {
            if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
                log.Printf("Temporary error while accepting connection: %s", netErr)
            }

            log.Fatalf("Unrecoverable error while accepting connection: %s", err)
            return
        }

        go handleTCPConn(conn)  // check below
    }
}


func handleTCPConn(conn net.Conn) {
    log.Printf("Accepting TCP connection from %s with destination of %s", conn.RemoteAddr().String(), conn.LocalAddr().String())
    defer conn.Close()
    
    remoteConn, err := conn.(*tproxy.Conn).DialOriginalDestination(false)
    if err != nil {
        log.Printf("Failed to connect to original destination [%s]: %s", conn.LocalAddr().String(), err)
        return
    } 
    defer remoteConn.Close()

    var streamWait sync.WaitGroup
    streamWait.Add(2)

    streamConn := func(dst io.Writer, src io.Reader) {
        io.Copy(dst, src)
        streamWait.Done()
    }

    go streamConn(remoteConn, conn)
    go streamConn(conn, remoteConn)

    streamWait.Wait()
}

根据我的理解,我画了这张图:

你看,handleTCPConn 创建了两个 goroutines 用于传输两个方向(左 -> 右;右 -> 左)的流量,

我的问题是:

  1. 你看代码使用sync.WaitGroup,如果他们只发送left-> right流量,没有相反方向的流量,所以handleTCPConn不会结束, 正确的?如果是,listenTCP for 循环将创建许多 handleTCPConn 函数调用,这个程序没有问题吗?

  2. 每次使用handleTCPConn,都会创建一个到远程服务器的TCP连接。

remoteConn, err := conn.(*tproxy.Conn).DialOriginalDestination(false)

我的问题还是问题1,可以看到handleTCPConn双向传输一次流量,然后结束,handleTCPConn结束时TCP连接是否关闭? 如果他们只传输文件的部分数据(从应用层来看),它是否也被关闭了? (我的意思是,如果 A->B->C: 部分数据,则 C->B->A: ACK)。

根据 golang 文档,https://pkg.go.dev/io#Copy

Copy copies from src to dst until either EOF is reached on src or an error occurs. It returns the number of bytes copied and the first error encountered while copying, if any.

所以当你启动这个程序时,它会坐在那里等你点击'proxy',然后将你的字节从源发送到目的地......当目的地响应时它会复制所有这些字节都回来了。如果目的地不写任何字节并且不关闭连接我相信它会永远坐在那里,等待远端关闭套接字或响应。

如果您建立此连接并且远程端开始发送数据(首先没有请求),情况也是如此。如果“本地”端从不发送任何字节并且不关闭连接,则此代码也将永远等待。

只要远程端优雅地关闭连接,这段代码就应该在收到“0”字节并且没有错误的情况下退出。如果远程端发送重置,您应该会收到某种错误