Linux下Tcp保活时间默认多少,C/C++网络编程中的TCP保活
在默認的情況下,TCP連接是沒有?;畹男奶?。這就是說,當一個TCP的socket,客戶端與服務端誰也不發送數據,會一直保持著連接。這其中如果有一方異常掉線,另一端永遠也不可能知道。這對于一些服務型的程序來說,將是災難性的后果。
所以,必須對創建的socket,啟用?;钚奶?#xff0c;即Keepalive選項。
啟用Keepalive
對于WIN32或者Linux平臺來說,設置socket的Keepalive都很簡單,只需使用setsockopt設置SO_KEEPALIVE即可。
setsockopt的函數原型在Linux環境下為:[cpp]#include?
#include?
intsetsockopt(ints,intlevel,intoptname,
constvoid*optval,
socklen_t?optlen);,在WIN32平臺下為 [cpp]#include?
intsetsockopt(ints,intlevel,intoptname,
constchar*optval,
intoptlen);
因為const void *可以接受const char *型的參數,所以為了代碼的跨平臺編譯考慮,可以采用以下代碼來設置TCP的Keepalive選項。[cpp]alive?=?1;
if(setsockopt
(fd,?SOL_SOCKET,?SO_KEEPALIVE,?(constchar*)?&alive,
sizeofalive)?!=?0)
{
log_warn?("Set?keep?alive?error:?%s.\n",?strerror?(errno));
return-1;
}
這樣,對于TCP的連接,就啟用了系統默認值的?;钚奶?/p>
Linux環境下的TCP Keepalive參數設置
為什么說是系統默認值的呢?因為有這樣幾個值,我們并沒有手動設置,是采用的系統默認值。即,
多長時間發送一次保活心跳?
如果沒有返回,多長時間再重試發送?
重試幾次為失敗?
如果是Linux操作系統,這三個值分別為[plain]#?cat?/proc/sys/net/ipv4/tcp_keepalive_time
7200
#?cat?/proc/sys/net/ipv4/tcp_keepalive_intvl
75
#?cat?/proc/sys/net/ipv4/tcp_keepalive_probes
9
這就是說,在Linux系統下,如果對于TCP的socket啟用了Keepalive選項,則會在7200秒(即兩個小時)沒有數據后,發起KEEPALIVE報文。如果沒有回應,則會在75秒后再次重試。如果重試9次均失敗,則認定連接已經失效。TCP的讀取操作,將返回0。
這對于我們大多數應用來說,前兩個時間值都有點太長了。
我們可以通過重設上面三個值,來使得操作系統上運行的所有啟用了Keepalive選項的TCP的socket的行為更改。
我們也可以只針對我們自己創建的socket,重設這三個值。它們分別對應TCP_KEEPIDLE、TCP_KEEPINTL和TCP_KEEPCNT的選項值,同樣可以使用setsockopt進行設置。[cpp]#include?
#include?
#include?
#include?
#include?
#include?
#include?
#include?
int
socket_set_keepalive?(intfd)
{
intret,?error,?flag,?alive,?idle,?cnt,?intv;
/*?Set:?use?keepalive?on?fd?*/
alive?=?1;
if(setsockopt
(fd,?SOL_SOCKET,?SO_KEEPALIVE,?&alive,
sizeofalive)?!=?0)
{
log_warn?("Set?keepalive?error:?%s.\n",?strerror?(errno));
return-1;
}
/*?10秒鐘無數據,觸發?;顧C制,發送?;畎?*/
idle?=?10;
if(setsockopt?(fd,?SOL_TCP,?TCP_KEEPIDLE,?&idle,sizeofidle)?!=?0)
{
log_warn?("Set?keepalive?idle?error:?%s.\n",?strerror?(errno));
return-1;
}
/*?如果沒有收到回應,則5秒鐘后重發?;畎?*/
intv?=?5;
if(setsockopt?(fd,?SOL_TCP,?TCP_KEEPINTVL,?&intv,sizeofintv)?!=?0)
{
log_warn?("Set?keepalive?intv?error:?%s.\n",?strerror?(errno));
return-1;
}
/*?連續3次沒收到?;畎?#xff0c;視為連接失效?*/
cnt?=?3;
if(setsockopt?(fd,?SOL_TCP,?TCP_KEEPCNT,?&cnt,sizeofcnt)?!=?0)
{
log_warn?("Set?keepalive?cnt?error:?%s.\n",?strerror?(errno));
return-1;
}
return0;
}
WIN32環境下的TCP Keepalive參數設置
而WIN32環境下的參數設置,就要麻煩一些,需要使用另外的一個函數WSAIoctl和一個結構struct tcp_keepalive。
它們的原型分別為:[cpp]#include?
#include?
intWSAIoctl(
SOCKET?s,
DWORDdwIoControlCode,
LPVOIDlpvInBuffer,
DWORDcbInBuffer,
LPVOIDlpvOutBuffer,
DWORDcbOutBuffer,
LPDWORDlpcbBytesReturned,
LPWSAOVERLAPPED?lpOverlapped,
LPWSAOVERLAPPED_COMPLETION?lpCompletionRoutine
);
structtcp_keepalive?{
u_long?onoff;
u_long?keepalivetime;
u_long?keepaliveinterval;
};
在這里,使用WSAIoctl的時候,dwIoControlCode要使用SIO_KEEPALIVE_VALS,lpvOutBuffer用不上,cbOutBuffer必須設置為0。
struct tcp_keepalive結構的參數意義為:
onoff,是否開啟KEEPALIVE; keepalivetime,多長時間觸發Keepalive報文的發送; keepaliveinterval,多長時間沒有回應觸發下一次發送。
注意:這里兩個時間單位都是毫秒而不是秒。[cpp]#include?
#include?
int
socket_set_keepalive?(intfd)
{
structtcp_keepalive?kavars[1]?=?{
1,
10?*?1000,/*?10?seconds?*/
5?*?1000/*?5?seconds?*/
};
/*?Set:?use?keepalive?on?fd?*/
alive?=?1;
if(setsockopt
(fd,?SOL_SOCKET,?SO_KEEPALIVE,?(constchar*)?&alive,
sizeofalive)?!=?0)
{
log_warn?("Set?keep?alive?error:?%s.\n",?strerror?(errno));
return-1;
}
if(WSAIoctl
(fd,?SIO_KEEPALIVE_VALS,?kavars,sizeofkavars,?NULL,sizeof(int),?&ret,?NULL,
NULL)?!=?0)
{
log_warn?("Set?keep?alive?error:?%s.\n",?strerror?(WSAGetLastError?()));
return-1;
}
return0;
}
總結
以上是生活随笔為你收集整理的Linux下Tcp保活时间默认多少,C/C++网络编程中的TCP保活的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux到不了启动界面,Linux 界
- 下一篇: linux基于文本的配置工具,Linux