英文:
Correct usage of io.Copy to proxy data between two net.Conn TCP connections in Golang?
问题
在Golang中,复制两个TCP连接之间的数据有不同的用法。以下是两种常见的模式:
模式一:
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()
}
模式二:
package main
import (
"io"
"net"
"sync"
)
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()
}
这两种模式都可以在测试中正常工作,但是你可能会担心边缘情况。其中,模式一在两个goroutine结束后再关闭连接,而模式二在关闭连接之前就结束了goroutine。具体使用哪种模式取决于你的需求和场景。
英文:
There are conflicting usages of io.Copy
and I want to know the correct way to copy data between two TCP connections in Golang?
Some people say to call Close inside the goroutines, and others don't
https://stackoverflow.com/questions/32460618/golang-1-5-io-copy-blocked-with-two-tcpconn
https://github.com/LiamHaworth/go-tproxy/blob/master/example/tproxy_example.go#L159
Here are the two common patterns I've seen online, both seemly work fine in my tests, but I'm worried about edge cases and I cannot figure out which, if any, is correct?
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()
}
答案1
得分: 2
代理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)
// 向对等方发送信号,表示没有更多的数据了。
conn1.CloseWrite()
}()
go func() {
defer wg.Done()
io.Copy(conn2, conn1)
// 向对等方发送信号,表示没有更多的数据了。
conn2.CloseWrite()
}()
wg.Wait()
}
英文:
Proxy 1: The proxy deadlocks when a peer waits for EOF before the peer closes the connection.
Proxy 2: The proxy can close a connection before all data is read from the connection.
This code fixes both problems:
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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论