程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 網絡編程釋疑之:TCP半開連接的處理

網絡編程釋疑之:TCP半開連接的處理

編輯:關於C語言

熟悉基於TCP協議進行linux高性能、高並發服務端編程的朋友肯定應該知道每個文件描述符及其所占的資源對並發量的影響。在這種7*24甚至*365不間斷運行的服務器上,一個描述符被浪費,兩個被浪費...如果被浪費的多了,那還何談高並發,高性能。除去文件描述被正常占用的情況外,是什麼導致了我們可用的文件描述符越來越少呢?

什麼是半開連接?

當客戶端與服務器建立起正常的TCP連接後,如果客戶主機掉線網線斷開)、電源掉電、或系統崩潰,服務器進程將永遠不會知道通過我們常用的select,epoll監測不到斷開或錯誤事件),如果不主動處理或重啟系統的話對於服務端來說會一直維持著這個連接,任憑服務端進程如何望穿秋水,也永遠再等不到客戶端的任何回應。這種情況就是半開連接,浪費了服務器端可用的文件描述符。

如何處理?

熟悉套接字通用選項的朋友一定已經有了想法。TCP套接字不是有個保持存活選項SO_KEEPALIVE嘛,如果在兩個小時之內在該套接字的任何一個方向上都沒數據交換,TCP就自動給對端發送一個保持存活探測分節,如果此TCP探測分節的響應為RST,說明對端已經崩潰且已經重新啟動,該套接字的待處理錯誤被置為ECONNRESET,套接字本身則被關閉。如果沒有對此TCP探測分節的任何響應,該套接字的處理錯誤就被置為ETIMEOUT,套接字本身則被關閉。

確實,這個選項確實可以處理我們前面遇到的TCP半開連接的問題,但是默認兩小時間隔探測的實時性是不是差了些呢?當然,我們可以通過修改內核參數改小時間間隔,完美了吧?但是必須注意的是大多數內核是基於整個內核維護這些時間參數的,而不是基於每個套接字維護的,因此如果把無活動周期從兩小時改為比如)2分鐘,那將影響到該主機上所有開啟了此選項的套接字。我想大家都不會願意承擔服務器端的這種不確定性吧。

沒關系,其實我們可以在應用層模擬SO_KEEPALIVE的方式,用心跳包來模擬保活探測分節。由於服務器通常要承擔成千上萬的並發連接,所以肯定是由客戶端在應用層進行心跳來模擬保活探測分節,客戶端多次收不到服務器的響應時可終止此TCP連接,而服務端可監測客戶端的心跳包,若在一定時間間隔內未收到任何來自客戶端的心跳包則可以終止此TCP連接,這樣就有效避免了TCP半開連接的情況。


本文出自 “永遠的朋友” 博客,請務必保留此出處http://yaocoder.blog.51cto.com/2668309/1309358

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved