今天在做一個模擬登錄的功能,實現(xiàn)使用掃描二維碼的方式實現(xiàn)某Q的登錄刻肄。詳細過程省略瓤球,只說遇到坑與解決方案。
功能中使用的模塊如下:
- http
- https
- bluebird
- xml2js
在發(fā)生對HTTPS的POST請求時敏弃,控制臺出現(xiàn): Error: socket hand up.
錯誤卦羡。
解決過程
1. 測試是否為相應的api服務器出現(xiàn)問題
我使用瀏覽器打開相應的api網(wǎng)址绿饵,瀏覽器中返回了正常的提示信息拟赊。說明api服務器沒問題粹淋。
2. 測試http/https模塊內(nèi)部機制出現(xiàn)問題
我把網(wǎng)址的修改為 快捎官網(wǎng) 。然后再運行屋匕,發(fā)現(xiàn)請求正常返回了頁面文本过吻,說明http/https模塊內(nèi)部機制可以正常使用蔗衡。
為什么別的網(wǎng)址可以正常請求而某Q的api路徑卻請求不成功?是header頭設置有誤绞惦?還是我當前請求的IP被拒絕請求?本著滿腦子的疑問樊展,我繼續(xù)進行了測試。
3. 完善請求信息雷酪,并使用其他開發(fā)語言進行同樣的請求涝婉,以進行結果對比
由于不敢確定所有的請求信息都是正確的,于是我使用java語言和python語言都做了一個副本墩弯,用來請求以進行結果對照渔工。最終發(fā)現(xiàn),所有請求數(shù)據(jù)都一致的情況下引矩,java語言和python語言可以成功地返回正確結果,而Node.js卻報錯:Error: socket hand up
氛谜。
這時我心頭有千萬頭草泥馬在奔騰~~~@#$%%&*#@#$%
但程序員是不會這么容易就放棄的值漫,何況遇到這個問題的那個還有強迫癥织盼。我要克服你...
---- 繼續(xù)苦逼找尋答案中... ----
4. 轉(zhuǎn)機
詳細認(zhuang)真(bi)地閱讀了NodeJs的 http.Agent 類的文檔,才晃(yi)然(lian)大(meng)誤(bi)晚吞。原來Node.js中谋国,發(fā)起的HTTP請求,會被放入v8的網(wǎng)絡請求隊列中捌蚊,而Agent則是負責管理HTTP客戶端的連接持久性和重用性近弟。它為給定的主機和端口維護等待請求的隊列,為每個隊列重復使用一個單一的Socket連接,直接到隊列為空窗宦,此時Socket被銷毀或被重新放進池中,在該池中保持對同一主機端口的請求再次使用媒怯。而這個Socket被銷毀還是保留髓窜,取決于keepAlive的配置。
所以這就是為什么我的程序會出現(xiàn)socket hand up錯誤了鳖敷,因為我在開發(fā)模擬登錄功能時程拭,登錄成功后,有一個請求一直在輪詢檢查新消息屋吨。而另一方面山宾,我會進行其他的數(shù)據(jù)api請求鳍徽,所以,當輪詢的socket一直得不到釋放绷杜,那么其他的socket就一直處于等待(Pending)狀態(tài)鞭盟,當超時時間到達瑰剃,就會報出Error: socket hand up
錯誤。
5. 解決方案
經(jīng)過以上探討粤剧,得出解決方案: 去除Socket代理挥唠,禁用請求隊列的重用,讓每次發(fā)起的請求都是新的Socket弧关。
如下代碼:
http.post({
hostname: 'localhost',
port: 80,
path: '/',
agent: false // 禁用agent
}, res => {
// 對響應數(shù)據(jù)進行處理
})
一番努力,終于解決了宽堆。