【问题标题】:Golang HTTP Post error: connection refusedGolang HTTP Post 错误:连接被拒绝
【发布时间】:2015-04-07 05:26:55
【问题描述】:

我正在尝试在运行 PHP 应用程序的端口 8080 上向 localhost 发送一个发布请求。

卷曲工作正常:

curl --data "key=asdf" http://localhost:8080/

但在 Go 中我收到以下错误:

Post http://localhost:8080: dial tcp 127.0.0.1:8080: connection refused

代码如下:

func submitForm(value string){
    resp, err := http.PostForm("http://localhost:8080", url.Values{"key": {value}})
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    _, err = ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("status = ",resp.Status)
}
submitForm("asdf")

我用httpry监控http流量,发现没有生成http请求但是有一些包:

4 packets received, 0 packets dropped, 0 http packets parsed

更多事实:

  • 我的操作系统是 Linux
  • 我使用 PHP 的内置网络服务器。使用以下命令启动服务器:

    php -S 本地主机:8080

【问题讨论】:

  • 这段代码对我来说很好用。如何调用submitForm 以及如何启动 php 服务器?服务器和这个 go 代码是在同一台机器上运行的吧?
  • 我这样称呼它: submitForm("asdf") 服务器是在同一台机器上启动的: php -S localhost:8080 你认为这是 PHP(不是 Go 的)的错吗?跨度>
  • 可能。什么版本的php?比较curl和go之间的http请求可能会很有趣,看看php服务器正在寻找的标头是否存在差异。
  • PHP 5.6.4 如何查看 http 请求?由于请求被拒绝,在 php 中打印 $_POST 将不起作用。
  • 对,我以为你可以打印 go 请求,但你不能,因为你使用 PostForm。而且我不确定如何使 php 服务器更详细。 Go 中的 Get 或 Post 函数是否有效?您是否尝试过使用较低级别的 go 函数构建请求,如此处所述 golang.org/pkg/net/http

标签: post go


【解决方案1】:

这个问题似乎在 Go 1.6 中得到解决。作为参考,原始答案如下。


这里的问题是 Go 的 net.Dialer 默认只建立 IPv4 连接(这似乎是一个错误),但您的 PHP 服务器在 IPv6 上侦听。

当您运行 php -S localhost:8080 时,它正在做(大部分)正确的事情并绑定到 IPv6 地址 ::1。它不绑定到 IPv4。

对于大多数软件来说这不是问题,knows to attempt IPv6 connections first,但是当你调用 http.PostForm() 时会发生什么,net.http 使用它的DefaultTransport,默认情况下它使用net.Dialer Dial( ) 进行传出连接。 Dial() 尝试解析地址,然后我们在 src/net/ipsock.go 的解析器中结束 deep,我们发现 Go 开发人员在尝试工作时故意搞砸了围绕别的东西:

        // We'll take any IP address, but since the dialing
        // code does not yet try multiple addresses
        // effectively, prefer to use an IPv4 address if
        // possible. This is especially relevant if localhost
        // resolves to [ipv6-localhost, ipv4-localhost]. Too
        // much code assumes localhost == ipv4-localhost.

这显然是个问题,因为 IPv6 应该是默认和首选协议。 Linux 和 PHP 行为正确,而 Go 本身则不然。

上面的评论是在 1.4 分支中找到的。在 master 分支中,这已被完全重写,但在新代码中,是否首选 IPv6 或 IPv4 地址并不明显。它很可能是不确定的;我没有花太多时间看它。根据我在 GitHub 上发现的问题,(见下文)实际上不太可能修复。

与此同时,您可以通过将 Go 连接到 ::1 或将 PHP 绑定到 127.0.0.1 来解决此错误。您也可以构建自己的具有正确行为的 RoundTripper,但这可能工作量太大,除非您实际上在访问支持 IPv6 的服务时遇到问题(最终我们都会遇到问题,所以这确实需要修复)。

一些相关的 Go 问题包括:

以及其他几个不再相关的旧问题,因为代码早已被重写......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 2019-06-15
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多