我想用net包建立一个简单的代理,但是上游在不使用go例程的情况下,没有发回任何数据。

问题描述 投票:0回答:1

我写了这个简单的代理服务器与 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应该在上游回复后才写?那么有一个go的例程是怎样的呢?io.Copy(upstream, conn) 部分解决这个问题?

go goroutine
1个回答
0
投票

io.Copy不应该屏蔽吗?

是的。"从src复制到dst,直到src上达到EOF或发生错误。". 由于这是一个网络连接,这意味着它在客户端关闭连接后返回。客户端是否以及何时关闭连接取决于应用协议。例如,在HTTP中,它可能永远不会发生。

有一个goroutine如何解决这个问题?

因为这样的话,第二个Copy可以在客户端还在连接的时候执行,让上游写出它的响应。如果没有goroutine,什么也没有从上游读取,所以很可能在它的写调用上被阻塞。

客户端(大概)等待响应,代理等待客户端关闭连接,上游等待代理开始读取响应:没有人可以取得进展,你就陷入了死锁。

© www.soinside.com 2019 - 2024. All rights reserved.