我用 net
编写了这个简单的代理服务器包,我希望将来自 8001 的本地服务器的连接代理到通过 8000 的任何传入连接。当我转到浏览器并尝试它时,我收到拒绝连接错误。
package main
import (
"net"
"log"
"io"
)
func main() {
l, err := net.Listen("tcp", "localhost:8000")
if err != nil {
log.Fatal(err)
}
for {
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
go proxy(conn)
}
}
func proxy(conn net.Conn) {
defer conn.Close()
upstream, err := net.Dial("tcp","localhost:8001")
if err != nil {
log.Print(err)
return
}
defer upstream.Close()
io.Copy(upstream, conn)
io.Copy(conn, upstream)
}
但是如果我在代理函数中更改以下行
io.Copy(upstream, conn)
io.Copy(conn, upstream)
到
go io.Copy(upstream, conn)
io.Copy(conn, upstream)
然后它按预期工作。不应该
io.Copy(upstream, conn)
阻止io.Copy(conn, upstream)
?根据我的理解,conn应该只有在上游回复后才写?以及 io.Copy(upstream, conn)
的 go 例程如何?部分解决这个?
最佳答案
Shouldn't io.Copy block?
是的。 "Copy copies from src to dst until either EOF is reached on src or an error occurs." .由于这是一个网络连接,这意味着它在客户端关闭连接后返回。客户端是否以及何时关闭连接取决于应用程序协议(protocol)。例如,在 HTTP 中它可能永远不会发生。
How does having a goroutine solve this?
因为这样第二个 Copy 可以在客户端仍然连接时执行,从而允许上游写入其响应。没有 goroutine 就不会从上游读取任何内容,因此它可能会在其 write 调用时被阻塞。
客户端(大概)等待响应,代理等待客户端关闭连接,上游等待代理开始读取响应:没有人可以取得进展,你陷入了僵局。
关于go - 我正在尝试使用 net 包构建一个简单的代理,但是当我不使用 go 例程时,上游没有发回任何数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62339715/