正确使用io,复制到Golang中两个网络连接TCP连接之间的代理数据?

kcwpcxri  于 2023-02-14  发布在  Go
关注(0)|答案(1)|浏览(195)

io.Copy的用法有冲突,我想知道在Golang中两个TCP连接之间复制数据的正确方法?
有些人说在goroutine中调用Close,而有些人则不这么https://github.com/LiamHaworth/go-tproxy/blob/master/example/tproxy_example.go#L159
下面是我在网上看到的两种常见模式,它们在我的测试中似乎都工作得很好,但我担心边缘情况,我不知道哪种模式是正确的?

package main

import (
    "io"
    "net"
    "sync"
)

func proxy1(conn1, conn2 net.Conn) {
    defer conn1.Close()
    defer conn2.Close()

    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        io.Copy(conn1, conn2)
        wg.Done()
    }()
    go func() {
        io.Copy(conn2, conn1)
        wg.Done()
    }()

    wg.Wait()
}

func proxy2(conn1, conn2 net.Conn) {
    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        io.Copy(conn1, conn2)
        wg.Done()
        conn1.Close()
    }()
    go func() {
        io.Copy(conn2, conn1)
        wg.Done()
        conn2.Close()
    }()

    wg.Wait()
}
vq8itlhq

vq8itlhq1#

代理1:当对等体在关闭连接之前等待EOF时,代理死锁。
代理2:代理可以在从连接读取所有数据之前关闭连接。
此代码修复了这两个问题:

func proxy(conn1, conn2 *net.TCPConn) {
    defer conn1.Close()
    defer conn2.Close()

    var wg sync.WaitGroup
    wg.Add(2)

    go func() {
        defer wg.Done()
        io.Copy(conn1, conn2)
        // Signal peer that no more data is coming.
        conn1.CloseWrite()
    }()
    go func() {
        defer wg.Done()
        io.Copy(conn2, conn1)
        // Signal peer that no more data is coming.
        conn2.CloseWrite()
    }()

    wg.Wait()
}

相关问题