Linux SO_KEEPALIVE属性,心跳
對于面向連接的TCP socket,在實際應用中通常都要檢測對端是否處于連接中,連接端口分兩種情況:
1、連接正常關閉,調用close() shutdown()連接優雅關閉,send與recv立馬返回錯誤,select返回SOCK_ERR;
2、連接的對端異常關閉,比如網絡斷掉,突然斷電.
對于第二種情況,判斷連接是否斷開的方法有一下幾種:
1、自己編寫心跳包程序,簡單的說就是自己的程序加入一條線程,定時向對端發送數據包,查看是否有ACK,根據ACK的返回情況來管理連接。此方法比較通用,一般使用業務層心跳處理,靈活可控,但改變了現有的協議;
2、使用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端終止連接。
修改三個參數的系統默認值
臨時方法:向三個文件中直接寫入參數,系統重啟需要重新設置;
臨時方法:sysctl -w net.ipv4.tcp_keepalive_intvl=20
全局設置:可更改/etc/sysctl.conf,加上:
net.ipv4.tcp_keepalive_intvl = 20
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_time = 60
?
/* Set TCP keep alive option to detect dead peers. The interval option* is only used for Linux as we are using Linux-specific APIs to set* the probe send time, interval, and count. */ int anetKeepAlive(char *err, int fd, int interval) {int val = 1;//開啟keepalive機制if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){anetSetError(err, "setsockopt SO_KEEPALIVE: %s", strerror(errno));return ANET_ERR;}#ifdef __linux__/* Default settings are more or less garbage, with the keepalive time* set to 7200 by default on Linux. Modify settings to make the feature* actually useful. *//* Send first probe after interval. */val = interval;if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {anetSetError(err, "setsockopt TCP_KEEPIDLE: %s\n", strerror(errno));return ANET_ERR;}/* Send next probes after the specified interval. Note that we set the* delay as interval / 3, as we send three probes before detecting* an error (see the next setsockopt call). */val = interval/3;if (val == 0) val = 1;if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {anetSetError(err, "setsockopt TCP_KEEPINTVL: %s\n", strerror(errno));return ANET_ERR;}/* Consider the socket in error state after three we send three ACK* probes without getting a reply. */val = 3;if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {anetSetError(err, "setsockopt TCP_KEEPCNT: %s\n", strerror(errno));return ANET_ERR;} #endifreturn ANET_OK; }
?
總結
以上是生活随笔為你收集整理的Linux SO_KEEPALIVE属性,心跳的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux线程间同步(1)读写锁
- 下一篇: 回调函数的应用