對(duì)于面向連接的TCP socket,在實(shí)際應(yīng)用中通常都要檢測(cè)對(duì)端是否處于連接中,連接端口分兩種情況:
- 1、連接正常關(guān)閉,調(diào)用close() shutdown()連接優(yōu)雅關(guān)閉,send與recv立馬返回錯(cuò)誤,select返回SOCK_ERR;
- 2妄讯、連接的對(duì)端異常關(guān)閉,比如網(wǎng)絡(luò)斷掉,突然斷電.
對(duì)于第二種情況,判斷連接是否斷開的方法有一下幾種:
- 自己編寫心跳包程序,簡(jiǎn)單的說(shuō)就是自己的程序加入一條線程,定時(shí)向?qū)Χ税l(fā)送數(shù)據(jù)包,查看是否有ACK,根據(jù)ACK的返回情況來(lái)管理連接肠鲫。此方法比較通用,一般使用業(yè)務(wù)層心跳處理,靈活可控,但改變了現(xiàn)有的協(xié)議;
- 使用TCP的keepalive機(jī)制,UNIX網(wǎng)絡(luò)編程不推薦使用SO_KEEPALIVE來(lái)做心跳檢測(cè)(為什么??)。keepalive原理:TCP內(nèi)嵌有心跳包,以服務(wù)端為例,當(dāng)server檢測(cè)到超過(guò)一定時(shí)間
(/proc/sys/net/ipv4/tcp_keepalive_time 7200 即2小時(shí))
沒有數(shù)據(jù)傳輸,那么會(huì)向client端發(fā)送一個(gè)keepalive packet,此時(shí)client端有三種反應(yīng):
1榜轿、client端連接正常,返回一個(gè)ACK.server端收到ACK后重置計(jì)時(shí)器,在2小時(shí)后在發(fā)送探測(cè).如果2小時(shí)內(nèi)連接上有數(shù)據(jù)傳輸,那么在該時(shí)間的基礎(chǔ)上向后推延2小時(shí)發(fā)送探測(cè)包;
2幽歼、客戶端異常關(guān)閉,或網(wǎng)絡(luò)斷開。client無(wú)響應(yīng),server收不到ACK,在一定時(shí)間(/proc/sys/net/ipv4/tcp_keepalive_intvl 75 即75秒)
后重發(fā)keepalive packet
, 并且重發(fā)一定次數(shù)(/proc/sys/net/ipv4/tcp_keepalive_probes 9 即9次)
;
3谬盐、客戶端曾經(jīng)崩潰,但已經(jīng)重啟.server收到的探測(cè)響應(yīng)是一個(gè)復(fù)位,server端終止連接甸私。
SO_KEEPALIVE的缺點(diǎn):
根據(jù)MSDN的文檔,如果為socket設(shè)置了KEEPALIVE選項(xiàng)飞傀,TCP/IP棧在檢測(cè)到對(duì)方掉線后, 任何在該socket上進(jìn)行的調(diào)用(發(fā)送/接受調(diào)用)就會(huì)立刻返回皇型,錯(cuò)誤號(hào)是WSAENETRESET;同時(shí)砸烦,此后的任何在該socket句柄的調(diào)用會(huì)立刻失敗弃鸦,并返回WSAENOTCONN錯(cuò)誤。
該機(jī)制的缺點(diǎn):
- 一幢痘、SO_KEEPALIVE無(wú)法控制唬格,它會(huì)每時(shí)每刻都發(fā);
- 二、SO_KEEPALIVE設(shè)置空閑2小時(shí)才發(fā)送一個(gè)“保持存活探測(cè)分節(jié)”西轩,不能保證實(shí)時(shí)檢測(cè)员舵。對(duì)于判斷網(wǎng)絡(luò)斷開時(shí)間太長(zhǎng),對(duì)于需要及時(shí)響應(yīng)的程序不太適應(yīng)藕畔。
當(dāng)然也可以修改時(shí)間間隔參數(shù)马僻,但是會(huì)影響到所有打開此選項(xiàng)的套接口!關(guān)聯(lián)了完成端口的socket可能會(huì)忽略掉該套接字選項(xiàng)注服。
參考鏈接:
在Linux環(huán)境下使用TCP的keepalive機(jī)制:實(shí)現(xiàn)了心跳函數(shù)韭邓,代碼邏輯清晰(看代碼)
http://www.tuicool.com/articles/yAJ36bz
Linux SO_KEEPALIVE屬性:對(duì)非活動(dòng)連接的檢測(cè)方法跟出現(xiàn)的情況寫的比較細(xì)致(看描述)
http://blog.csdn.net/callinglove/article/details/38380673
LINUX C網(wǎng)絡(luò)編程中的心跳機(jī)制:解釋了不使用SO_KEEPALIVE的缺點(diǎn)
http://blog.csdn.net/yuyin86/article/details/24997175