Lwip 保活機制 1

文章轉自老衲五木的新浪博客

    保活功能是TCP很重要的一個特性,它在連接異常檢測,異常處理上起着至關重要的作用。一個網絡應用程序是否穩定可靠,連接的異常處理尤爲重要。很多人反應,LwIP做客戶端時,是不是很不穩定,經常會莫名掉線。老衲想說的是,應爲網絡,硬件,環境等等太多原因,掉線是正常的,你應該把它看作一種常態,你對連接異常的處理有哪些,處理的怎麼樣,這些決定了你的代碼的穩定性和可用性。
    服務器運行中突然斷電、服務器軟件異常莫名死機、通信過程中網絡故障、人爲拔掉網線等等,這些都屬於連接異常的範疇。
    LwIP內核中提供了TCP保活功能,用來隨時監測連接的可用性,如果連接不可用,內核會對該連接進行異常處理(通常是多次試探,失敗後斷開連接,並通知一個事件給用戶)。通常用戶可以收到一個可讀的事件,此時用戶對連接任何讀寫操作都會立即返回錯誤(socket的話errno記錄了具體的錯誤值),此時用戶的正確處理應該是關閉連接,而不是循環嘗試在連接上進行更多的數據發送或接收操作。當然,用戶可以選擇在後續某個恰當的時候重新打開連接(客戶端常用的方式是重新嘗試連接,連接失敗則重複嘗試),這些是用戶應用程序設計應該考慮的問題。
    那麼,在LwIP中如何應用保活特性呢?如果你使用的是socket編程,那麼很簡單:
        int opt = 1;
        setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(int));
    這句就可以開啓該連接上的保活功能,後續若連接異常,內核會在該socket通知一個可讀事件,此時用戶調用讀寫操作時,內核會返回錯誤。應用程序應及時對這種異常進行處理。
    
    如果你使用的是raw api編程,那流程可能比較麻煩,需要細分爲兩種情況:
1),如果你程序做的是服務器,那這種情況比較簡單,內核已經對每個連接默認開啓了保活功能,當連接異常時,內核會通知你一個err的回調。
2),如果你程序做的是客戶端,這種情況下比較麻煩,內核沒有默認給你打開保活功能,此時需要自己動手啦,通常在建立連接的時候這樣做即可:
        pcb = tcp_new();
        ip_set_option(pcb, SOF_KE EPALIVE);
    
    這樣,如果你的客戶端檢測到連接異常,則會有一個err回調到用戶程序,同樣,你需要在回調中處理這個異常。也可以在這裏重新發起一個連接嘗試。

    最後,需要指出的是,在內核中默認的一些保活參數的配置,可能並不一定能滿足你應用程序的需求,比如保活開始的時間、發送保活的時間間隔、一共發送多少次保活包等等,你可以在lwipopts.h裏面進行配置,比如:
#define LWIP_TCP_KEEPALIVE           1        //開啓用戶自定義保活時間,這個值如果爲0,則系統使用默認的保活時間參數(這些參數可能不是你想要的,比如內核默認在連接雙方都沒有數據交互2個小時後,再發送保活探測包,對於拔網線這種異常,2小時太久了,用戶期望能在越短的時間內檢測出異常越好)
#define TCP_KEEPIDLE_DEFAULT         60000    //60秒內連接雙方都無數據,則發起保活探測(該值默認爲2小時)
#define TCP_KEEPINTVL_DEFAULT        10000    //每10秒發送一次保活探測
#define TCP_KEEPCNT_DEFAULT          9            //一共發送9次保活探測包,如果這9個包對方均無迴應,則表示連接異常,內核關閉連接,併發送err回調到用戶程序

發佈了28 篇原創文章 · 獲贊 22 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章