天天看點

linux tcp 心跳程式,linux的KEEPALIVE屬性,心跳機制

對于面向連接配接的TCP socket,在實際應用中通常都要檢測對端是否處于連接配接中,連接配接端口分兩種情況:

1、連接配接正常關閉,調用close() shutdown()連接配接優雅關閉,send與recv立馬傳回錯誤,select傳回SOCK_ERR;

2、連接配接的對端異常關閉,比如網絡斷掉,突然斷電.

對于第二種情況,判斷連接配接是否斷開的方法有一下幾種:

自己編寫心跳包程式,簡單的說就是自己的程式加入一條線程,定時向對端發送資料包,檢視是否有ACK,根據ACK的傳回情況來管理連接配接。此方法比較通用,一般使用業務層心跳處理,靈活可控,但改變了現有的協定;

使用TCP的keepalive機制,UNIX網絡程式設計不推薦使用SO_KEEPALIVE來做心跳檢測(為什麼??)。keepalive原理:TCP内嵌有心跳包,以服務端為例,當server檢測到超過一定時間(/proc/sys/net/ipv4/tcp_keepalive_time 7200 即2小時)沒有資料傳輸,那麼會向client端發送一個keepalive packet,此時client端有三種反應:

1、client端連接配接正常,傳回一個ACK.server端收到ACK後重置計時器,在2小時後在發送探測.如果2小時内連接配接上有資料傳輸,那麼在該時間的基礎上向後推延2小時發送探測包;

2、用戶端異常關閉,或網絡斷開。client無響應,server收不到ACK,在一定時間(/proc/sys/net/ipv4/tcp_keepalive_intvl 75 即75秒)後重發keepalive packet, 并且重發一定次數(/proc/sys/net/ipv4/tcp_keepalive_probes 9 即9次);

3、用戶端曾經崩潰,但已經重新開機.server收到的探測響應是一個複位,server端終止連接配接。

SO_KEEPALIVE的缺點:

根據MSDN的文檔,如果為socket設定了KEEPALIVE選項,TCP/IP棧在檢測到對方掉線後, 任何在該socket上進行的調用(發送/接受調用)就會立刻傳回,錯誤号是WSAENETRESET;同時,此後的任何在該socket句柄的調用會立刻失敗,并傳回WSAENOTCONN錯誤。

該機制的缺點:

一、SO_KEEPALIVE無法控制,它會每時每刻都發;

二、SO_KEEPALIVE設定空閑2小時才發送一個“保持存活探測分節”,不能保證明時檢測。對于判斷網絡斷開時間太長,對于需要及時響應的程式不太适應。

當然也可以修改時間間隔參數,但是會影響到所有打開此選項的套接口!關聯了完成端口的socket可能會忽略掉該套接字選項。