使用golang终止来自IP层的http请求

使用golang终止来自IP层的http请求,http,go,tcp,Http,Go,Tcp,我正在使用golang向服务器发出http post请求。假设服务器当前已关闭(意味着服务器运行所在的计算机已关闭),则请求将停留在IP层。因此,我的程序无法继续执行。它无法继续到应用程序层。那么在golang有没有办法阻止这一切。 我正在使用以下代码 req, err := http.NewRequest("POST", url, bytes.NewReader(b)) if err != nil { return errors.Wrap(err,

我正在使用golang向服务器发出http post请求。假设服务器当前已关闭(意味着服务器运行所在的计算机已关闭),则请求将停留在IP层。因此,我的程序无法继续执行。它无法继续到应用程序层。那么在golang有没有办法阻止这一切。 我正在使用以下代码

req, err := http.NewRequest("POST", url, bytes.NewReader(b))
       if err != nil {
               return errors.Wrap(err, "new request error")
       }
resp, err := http.DefaultClient.Do(req)
       if err != nil {
               return errors.Wrap(err, "http request error")
       }
       defer resp.Body.Close()

如果从IP层找不到任何内容,是否可以添加任何内容来终止请求。

默认http客户端没有超时。您可以自己创建显式http.Client并设置超时:

var cl = &http.Client{
    Timeout: time.Second * 10,
}

resp, err := cl.Do(req)

if err != nil {
    // err will be set on timeout
    return errors.Wrap(err, "http request error")
}
defer resp.Body.Close()

如果服务器在请求的中间不再应答,则可以处理超时。

< P>使用非默认<代码> http.Trase,将其<代码>方言上下文字段设置为一个函数,该函数使用具有正确配置的超时/截止期限的自定义上下文。另一个选项是使用自定义的
net.Dialer

大概是这样的:

cli := http.Client{
    Transport: &http.Transport{
        DialContext: func (ctx context.Context, network, address string) (net.Conn, error) {
            dialer := net.Dialer{
                Timeout: 3 * time.Second,
            }
            return dialer.DialContext(ctx, network, address)
        },
    },
}

req, err := http.NewRequest(...)
resp, err := cli.Do(req)
请注意,根据
net.Dialer
的文档,传递给其
DialContext
的上下文可能超过拨号器本身设置的超时 正是我们需要的:拨号程序的
超时
字段精确控制 “拨号”(TCP连接建立),而您也可以武装您的 使用上下文(使用
HTTP.request.WithContext
)控制的HTTP请求 整个请求的超时,也可以随时取消(包括拨号步骤)


.

在本例中,@kostix所指的Transport肯定就是您想要的。传输和客户端对于并发使用也是安全的。但是请注意(我也建议您阅读有关客户端的内容),因为有许多不同的方法会影响您处理空闲连接的方式,而不仅仅是前面提到的拨号上下文

由于您可能需要设置您的
响应headertimeout

ResponseHeaderTimeout,如果非零,则指定 完全恢复后等待服务器响应头的时间 编写请求(包括其正文,如有)。这 时间不包括读取响应正文的时间

或者,如果您使用的是安全连接,则可能需要设置
TLSHandshakeTimeout

TLSHandshakeTimeout指定等待的最大时间量 等待TLS握手。零表示没有超时

为了可读性和可维护性,我建议您也可以创建一个函数来构建您的客户机,大致如下:

func buildClient(timeout time.Duration) *http.Client {
    tr := &http.Transport{
        IdleConnTimeout:       timeout,
        ResponseHeaderTimeout: timeout,
        TLSHandshakeTimeout:   timeout,
    }
    client := &http.Client{
        Transport: tr,
        Timeout:   timeout,
    }
    return client
}

嗯,HTTO请求将失败,错误将是来自package net的错误,表明拨号失败。所以:不,没有什么需要补充的:如果在IP层上找不到任何东西,它已经“终止”了请求?您能更具体地说明一下,在显示的代码中有什么不起作用吗?我正在向apache服务器发送一个数据包,我希望在2-3秒内收到一个ACK。但是http请求无法在该时间内处理。但是我的http请求被卡在ip层,搜索过程超过了我的确认时间。http中是否有fire and forget直接实现的功能或API。(不使用任何通道机制)好的。您需要一个http.Transport并填写DialContext。还可以看看包网。请更新问题。请按照建议更新问题。此答案不正确:您所指的超时工作在TCP/IP之上的一层上,不仅包括连接时间,还包括执行请求(以及获取服务器响应)的时间。这意味着,如果你把它设置为3秒(如OP所需),并且连接将在这个时间框架内完成,那么超时将有可能在实际数据交换的中间收获请求。换句话说,正如我所理解的,OP想要“快速失败”。如果服务器似乎已死机,而对它的请求有一个更大的超时(或根本没有超时),则在相反的情况下正常进行。这可能是,但这只是在我发布此答案后的评论中建议的。也许OP应该澄清一下。好的提示,但这里的
idlecontimeout
似乎有些离谱:它控制在创建TCP连接的请求完成后,成功建立的TCP连接将保持有效的时间(并且在此期间双方同意保持连接有效)。对于许多客户机请求快速连续地发送到同一服务器的情况,这是一个很好的修补方法,但我认为这与OP的情况没有多大关系,因此最好不要把它们弄糊涂;-)@kostix示例中列出的一些未直接提及的项目,为了说明目的,我加入了这些项目,以显示OP运输文件中有许多项目需要熟悉。