2013-03-05 81 views
2

我在通過下面的代碼寫入TCP端口的C++應用程序中實現Keepalive時間。沒有顯示,但我確實檢查了有效的退貨狀態,以驗證設置選項是否有效。Keepalive時間 - 在C++中不能減少到一分鐘以下

int option = 1; 
int keepalive_intvl = 1; 
int keepalive_count = 1; 
int keepalive_idle = 1; 

setsockopt(the_socket, SOL_SOCKET, SO_KEEPALIVE, &option, sizeof (int)); 
setsockopt(the_socket, SOL_TCP, TCP_KEEPINTVL, &keepalive_intvl, sizeof(int)); 
setsockopt(the_socket, SOL_TCP, TCP_KEEPCNT, &keepalive_count, sizeof(int)); 
setsockopt(the_socket, SOL_TCP, TCP_KEEPIDLE, &keepalive_idle, sizeof(int)); 

我的應用程序正在寫入TCP端口,並嘗試每秒寫入數次。

// write null packet to determine if connection is still good 
return (send(GetDescriptor(),(char*)NULL, 0, 0) != -1); 

每當我關閉其他,輸入連接,它需要一分鐘,我的申請報告,連接中斷,基於上面的測試。如果我有一個SIGPIPE處理程序函數,它也需要一分鐘時間才能被調用。

我看到的每個文檔都表明keepalive參數是以秒爲單位的,而不是分鐘。但是我無法在1分鐘之內檢測到丟失的連接。

我也試過改變系統變量keepalive討論在tldp.org討論,但無濟於事。

echo 1 > /proc/sys/net/ipv4/tcp_keepalive_time 
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_intvl 
echo 1 > /proc/sys/net/ipv4/tcp_keepalive_probes 

此行爲是否受另一個系統參數控制?與一些文檔相反,Keepalive參數實際上是在幾分鐘內?有什麼函數可以影響這個超時參數嗎?

+0

選項是一個int不INT32 – QuentinUK 2013-03-05 18:13:52

+0

@QuentinUK,他們在我的代碼相同。儘管如此,編輯清晰。 – Chance 2013-03-05 18:22:01

+0

您是否嘗試過實際檢查'setsockopt()'的返回碼? – 2013-03-05 18:32:26

回答

0

我可以通過TCP_LINGER2值更改總體存活時間。

每當我關閉輸入tcp進程,我使用netstat -an獲得以下行。

tcp  1  0 127.0.0.1:32962   127.0.0.1:7780   CLOSE_WAIT 
tcp  0  0 127.0.0.1:7780   127.0.0.1:32962   FIN_WAIT2 

我可以用兩種不同的方式更改這個FIN_WAIT2時間。

在系統級,根據該link,我可以通過修改系統文件如下更改:

% cat /proc/sys/net/ipv4/tcp_fin_timeout 
60 

[To change this to 3 seconds] 
# echo "3" > /proc/sys/net/ipv4/tcp_fin_timeout 

我的輸出TCP應用表明,該連接是在大約四秒鐘下降(我想象3爲等待時間,1爲保持活動空閒)。

我也可以改變這個在代碼中的個別插座的水平。在文件/usr/include/netinet/tcp.h,我看到下面的

#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */ 

所以,把下面的在我的代碼,

int wait_time = 3; 
setsockopt(the_socket, SOL_TCP, TCP_LINGER2, &wait_time,sizeof(int)); 

將具有不同的系統參數相同的影響。

我不與該應用程序級別的保持連接其他的答案一致是真的要走的路。並且,如所提到here

RFC 1122,節4.2.3.6表示沒有數據爲TCP 保活確認可能不能夠可靠地由路由器發送的; 這可能會導致有效的連接被丟棄。此外,不需要TCP/IP堆棧 支持保活在所有(和許多 嵌入式堆棧沒有),所以這種解決方案可能無法轉化爲其他 平臺。

然而,在非測試環境,我沒有訪問中,我可以實現應用程序級別的保持活動的另一側的TCP輸入,所以TCP持久連接可能是我唯一的選擇。

1

最好的辦法是應用層保持活躍;即每X秒發送一次無操作(NOP)消息,並期望合理快速的NOP確認(NOP-ACK)。另外,如果您的遠程連接關閉是「優雅」,那麼您的send應該立即解除封鎖。如果不是優美(如網元失敗),那麼你的應用層保持活動會檢測你的下一次X +(預期的響應時間)的損失......

+0

任何一種應用層保持活動的TCP是會出現問題的,最終,它難以適應RTT,抖動,暫時的連接丟失......。有2個時間關鍵層總是一個壞主意(因此隧道幾乎總是使用UDP)。除此之外,您還將在一個流中混合使用應用程序和Keepalive數據,這非常容易出錯。 – KillianDS 2013-03-05 19:03:49

+0

當您的保持時間大約爲幾秒時,RTT和抖動可以忽略不計。如果TCP層不處理暫時的連接丟失,那麼你的應用程序必須處理這個問題。我會同意,如果時間緊迫,TCP-acks強加的所有額外流量都會浪費,UDP是更好的選擇。 – mark 2013-03-05 19:15:33

+0

問題是,我真的沒有訪問另一端(另一個進程偵聽)。我在測試環境中做,但我不會一直。但是,是的,我同意,應用程序級保活將是我的首選方式。 – Chance 2013-03-05 19:26:00

1

TCP_KEEPCNT(因爲Linux 2.4) TCP在丟棄連接之前應該發送的最大Keepalive探測數量。這個選項不應該用在可移植的代碼中。

也許這可能是原因。你可以在你的應用程序中實現自己的活着,它應該很容易。如果沒有應用數據或保持活力的「心跳」來到,就開始捅另一端。