Golang 解决"Connection reset by peer"或"EOF"问题

原创
2016/12/19 20:28
阅读数 1.4W

【问题】

我编写了一个http Client程序代码如下:

// create a request
req, err := http.NewRequest(method, url, body)
if err != nil {
    return nil, err
}

// send JSON to firebase
resp, err := http.DefaultClient.Do(req)
if err != nil {
    return nil, err
}

if resp.StatusCode != http.StatusOK {
    return nil, fmt.Errorf("Bad HTTP Response: %v", resp.Status)
}

defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
    return nil, err
}

多次发给服务器后,几乎每次都会出现下面的错误:

ERROR 10108 socket.cpp:985 0x7fffe81426e0 recvmsg(62, 1): (104, "Connection reset by peer")
WARN 10108 server.cpp:467  0x7fffe80abd60-2 Unexpected SocketException

【原因】

        在解决问题之前需要了解关于go是如何实现connection的一些背景小知识:有两个协程,一个用于读,一个用于写(就是readLoop和writeLoop)。在大多数情况下,readLoop会检测socket是否关闭,并适时关闭connection。如果一个新请求在readLoop检测到关闭之前就到来了,那么就会产生EOF错误并中断执行,而不是去关闭前一个请求。

        我执行时建立一个新的连接并发送keep-alive,服务器收到后将我的keep-alive发回并立即关闭了连接。当这段程序执行后退出,再次执行时服务器已经关闭了连接,而我的客户端却仍在重用之前建立的连接,所以提示连接被重置;如果我不退出程序而使用for循环多次发送时,旧连接未及时关闭,新连接却到来,EOF的错误也就产生了。

【解决】

对 req 增加属性设置:

req.Close = true

它会阻止连接被重用,可以有效的防止这个问题,也就是Http的短连接

展开阅读全文
打赏
0
0 收藏
分享
加载中

引用来自“那句诺言”的评论

我并发1000请求,好像req.Close=true也不行的
请求都及时关闭了么?如果有用defer的话, 函数结束后才会释放的
2018/12/13 20:53
回复
举报
我并发1000请求,好像req.Close=true也不行的
2018/11/28 14:28
回复
举报
更多评论
打赏
2 评论
0 收藏
0
分享
返回顶部
顶部