這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
【問題】
我編寫了一個http Client程式碼如下:
// create a requestreq, err := http.NewRequest(method, url, body)if err != nil { return nil, err}// send JSON to firebaseresp, 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錯誤並中斷執行,而不是去關閉前一個請求。這裡也是如此,我執行時建立一個新的串連,這段程式執行完成後退出,再次開啟執行時伺服器並不知道我已經關閉了串連,所以提示串連被重設;如果我不退出程式而使用for迴圈多次發送時,舊串連未關閉,新串連卻到來,會報EOF。
【解決】
對 req 增加屬性設定:
req.Close = true
它會阻止串連被重用,可以有效防止這個問題,也就是Http的短串連