我正在读《黑帽围棋》这本书。我遇到了一个简单的 TCP 代理示例。它基本上只是转发请求并发回回复。代理代码的要点如下所示(已修改):func handle(src net.Conn) { dst, err := net.Dial("tcp", "example.com:80") if err != nil { log.Fatalln("Unable to connect to remote") } defer dst.Close() // Run in goroutine to prevent io.Copy from blocking go func() { if _, err := io.Copy(dst, src); err != nil { log.Fatalln("Something wrong src -> dst") } }() if _, err := io.Copy(src, dst); err != nil { log.Fatalln("Something wrong dst -> src") }}我不明白的部分是注释“在 goroutine 中运行以防止 io.Copy 阻塞”。我已经在有和没有将它包装在 goroutine 中的情况下运行它,它只适用于 goroutine,但我不明白为什么。我们不能io.Copy为请求运行一个阻塞,然后为响应运行另一个阻塞吗?我想我很难理解如果第一个io.Copy在 goroutine 中运行,我们如何保证排序。
2 回答
Helenr
TA贡献1780条经验 获得超4个赞
当您处理 TCP 流时,您必须处理双向的流量,从 src 到 dest 和从 dest 到 src。您可以通过两次复制操作来做到这一点。但是,复制将阻塞,直到它收到错误或 EOF(即套接字关闭),因此您必须将这些复制操作中的至少一个放到 goroutine 中。它的写入方式,一个复制操作将从一个套接字读取并写入另一个,另一个复制操作将执行相反的操作,直到出现错误或 EOF。当收到错误或 EOF 时,两个复制操作都将停止。
杨魅力
TA贡献1811条经验 获得超6个赞
io.Copy 函数在 reader 或 writer 返回错误(包括 io.EOF)后返回。如果 io.Copy 调用未在 Go 例程中运行,则在将任何数据从 dst 复制到 src 之前,所有数据都会从 src 复制到 dst。
- 2 回答
- 0 关注
- 279 浏览
添加回答
举报
0/150
提交
取消