java检测tcp存活_keep-alive 和 TCP存活检测
什么是keep-alive?
顧名思義即可,注意它只適用于TCP連接。系統會替你維護一個timer,時間到了,就會向remote peer發送一個probe package,當然里面是沒有數據的,對方就會返回一個應答,這時你就知道這個通道保持正常。
有什么用呢?
考慮下面這個場景,端點A和端B開始連接,三次握手,建立好了一個穩定的雙向通道。然后雙方發送完初始的數據后,進入等待狀態。這時候,拔掉B的電源插頭,B死掉了,它不可能有任何機會向A發送FIN包,或是其他數據來說明自己掛掉,需要終止連接。因此A只是簡單的繼續等待。然后重啟機器和應用程序,B又恢復原始的狀態,可是原本的連接已經沒有了,之后就可能有三種情況,雙方繼續傻等,或是B向A發起新的請求,最可能的還是A向B發送新的數據,這時B因為原有的socket已經死了,就返回一個RST,A關閉連接??聪旅娴膱D: _____ _____
| | | |
| A | | B |
|_____| |_____|
^ ^
|--->--->--->-------------- SYN -------------->--->--->---|
|---
|--->--->--->-------------- ACK -------------->--->--->---|
| |
| system crash ---> X
|
| system restart ---> ^
| |
|--->--->--->-------------- PSH -------------->--->--->---|
|---
| |
上面的場景就提出了一個需求,作為服務器端,可不能老是傻等是不是,當然timeout也是一個方案了,不過如果是IM這種類型的服務器,總不能用戶一段時間沒反應,就把它給踢了吧。
keep-alive還有另外一個有點trick的作用,考慮另外一個場景,一般的終端總是位于防火墻或是NAT后面,而這些設備限制于硬件,不可能處理任意數量的連接,在內部隊列滿的時候,總是要把最不活躍的連接給砍了的。這個時候keep-alive就可以發揮最用了??聪旅娴膱D:
_____ _____ _____
| | | | | |
| A | | NAT | | B |
|_____| |_____| |_____|
^ ^ ^
|--->--->--->---|----------- SYN ------------->--->--->---|
|---
|--->--->--->---|----------- ACK ------------->--->--->---|
| | |
| |
| | |
|--->- PSH ->---|
| | |
程序上如何使用呢?
無論是windows還是linux都實現了這個功能,你只需要設置socket的屬性即可,當然你也可自己實現這個功能,也就是定期發送心跳包.
先說linux平臺:
一般的實現如下,也就是說每過7200s空閑(兩個小時),就會發送一個探測包,如果沒有應答,就隔75s,再次發送,連續9次沒有反應,就判定該連接死了。
# 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
如何改呢,可以用直接該系統默認值,則全局都會有效,這似乎不大合適。 如果是程序中,則只要設置socket的屬性就行了,調用setsockopt,首先打開keep-alive功能:
int optval = 1;
socklen_t optlen = sizeof(optval);
if(setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) {
perror("setsockopt()");
close(s);
exit(EXIT_FAILURE);
}
然后設定要改的值,像這樣:
setsockopt (fd, SOL_TCP, TCP_KEEPIDLE, &newValue, optlen);
TCP_KEEPCNT: 代表 tcp_keepalive_probes
TCP_KEEPIDLE: 代表 tcp_keepalive_time
TCP_KEEPINTVL: 代表 tcp_keepalive_intvl
windows平臺上也是差不多:
windows中也是可以做出系統級別的調整的, 對于Win2K/XP/2003,可以從下面的注冊表項找到影響整個系統所有連接的參數:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]
“KeepAliveTime”=dword:006ddd00
“KeepAliveInterval”=dword:000003e8
“MaxDataRetries”=”5″
在程序中來設定的話,首先先打開keep-alive,跟在linux中是一樣的,
BOOL bKeepAlive = TRUE;
int nRet = ::setsockopt(socket_handle, SOL_SOCKET, SO_KEEPALIVE, (char*)&bKeepAlive, sizeof(bKeepAlive));
然后調整具體的參數,需要調用WSAIoctl
tcp_keepalive alive_in = {0};
tcp_keepalive alive_out = {0};
alive_in.keepalivetime = 5000;
alive_in.keepaliveinterval = 1000;
alive_in.onoff = TRUE;
unsigned long ulBytesReturn = 0;
nRet = WSAIoctl(socket_handle, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in), &alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL);
開啟Keepalive選項之后,對于使用IOCP模型的服務器端程序來說,一旦檢測到連接斷開,GetQueuedCompletionStatus函數將立即返回FALSE,使得服務器端能及時清除該連接、釋放該連接相關的資源。對于使用 select模型的客戶端來說,連接斷開被探測到時,以recv目的阻塞在socket上的select方法將立即返回SOCKET_ERROR,從而得知連接已失效,客戶端程序便有機會及時執行清除工作、提醒用戶或重新連接。
總結
以上是生活随笔為你收集整理的java检测tcp存活_keep-alive 和 TCP存活检测的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA共有几种窗体布局方式_在Java
- 下一篇: mysql 优化300例_MySQL配置