【发布时间】:2020-10-12 18:40:15
【问题描述】:
我正在阅读《黑帽围棋》这本书。我遇到了一个简单的 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 中运行,我想我很难理解我们如何保证订购。
【问题讨论】:
-
TCP是双工流;没有“请求”和“响应”,所以你不能复制一个然后另一个。
-
我了解 TCP,但我想你找到了我问题的核心。我正在考虑使用封装的 HTTP 数据包,而不是转发整个流。感谢您的帮助。
标签: go