為什麼保持長連線需要心跳包?
阿新 • • 發佈:2019-01-07
有一個問題不知道大家注意過沒有——為什麼socket客戶端在非正常斷開後,伺服器在很長一段時間內不會顯示客戶端斷開?沒有的話,大可以試試-。-
原因:
如果是正常終止客戶端程序,系統會對程序正在佔用的資源進行回收。此時客戶端所佔用的socket埠會被釋放,伺服器端也會被告知對方斷開socket連線了,因此終止與該客戶端的連線。而如果客戶端非正常斷開(比如客戶端主機突然斷電),則客戶端的作業系統會在第一時間產生中斷,保護作業系統。哪個作業系統還會特意耗費時間去回收socket資源←_←。所以即便客戶端明明已經斷開了連線,但伺服器卻遲遲沒辦法知道客戶端斷開的訊息。因此會在較長一段時間內不會告訴程式設計者“某客戶端已斷開”,即便你寫了在客戶端斷開後立刻回收資源的程式碼。
解決:
相信不少人都聽說過“心跳包”吧。保持客戶端與伺服器長連線的話,心跳包是必不可少的。設定閾值n,心跳間隔時間T,當伺服器在n*T的時間內沒有聽到客戶端的心跳,那麼就可以判定客戶端“死亡”了,主動與它斷開連線,回收資源。至於n和T怎麼設定,純看專案的需求和程式設計者的心情了。當然,心跳包的寫法很多種,可以是伺服器向客戶端發心跳要求迴應,也可以是客戶端直接向伺服器發心跳。不同的應用場景可能都不同。
血的經歷:
當網路延遲高於n*T的時候,唉……(曾經設定n=2,T=8s,然而網路延遲——20000ms……別問我這種奇蹟怎麼發生,你在區域網邊上開上百個路由器就知道了)