TCP Keepalive 詳解


TCP keepAlive含義:

在TCP中有一個Keep-alive的機制可以檢測死連接,原理很簡單,TCP會在空閑了一定時間后發送數據給對方:

1.如果主機可達,對方就會響應ACK應答,就認為是存活的。
2.如果可達,但應用程序退出,對方就發RST應答,發送TCP撤消連接。
3.如果可達,但應用程序崩潰,對方就發FIN消息。

4.如果對方主機不響應ack, rst,繼續發送直到超時,就撤消連接。這個時間就是默認的二個小時。

 

 

在一個正常的TCP連接上,當我們用無限等待的方式調用下面的Recv或Send的時候:

   ret=recv(s,&buf[idx],nLeft,flags);

   或

   ret=send(s,&buf[idx],nLeft,flags);

   如果TCP連接被對方正常關閉,也就是說,對方是正確地調用了closesocket(s)或者shutdown(s)的話,那么上面的Recv或Send調用就能馬上返回,並且報錯。這是由於closesocket(s)或者shutdown(s)有個正常的關閉過程,會告訴對方“TCP連接已經關閉,你不需要再發送或者接受消息了”。但是,如果是網線突然被拔掉,TCP連接的任何一端的機器突然斷電或重啟動,那么這時候正在執行Recv或Send操作的一方就會因為沒有任何連接中斷的通知而一直等待下去,也就是會被長時間卡住。這種情形解決的辦法是啟動TCP編程里的keepAlive機制。

    struct TCP_KEEPALIVE inKeepAlive = {0};
    unsigned long ulInLen = sizeof(struct TCP_KEEPALIVE);
    struct TCP_KEEPALIVE utKeepAlive = {0};
    unsigned long ulOutLen = sizeof(struct TCP_KEEPALIVE);
    unsigned long ulBytesReturn = 0;

    inKeepAlive.onoff=1;
    inKeepAlive.keepaliveinterval=5000; //單位為毫秒
    inKeepAlive.keepalivetime=1000;      //單位為毫秒
    ret=WSAIoctl(s, SIO_KEEPALIVE_VALS, (LPVOID)&inKeepAlive, ulInLen, 
                          (LPVOID)&outKeepAlive, ulOutLen, &ulBytesReturn, NULL, NULL);

   此處的keepalivetime表示的是TCP連接處於暢通時候的探測頻率,一旦探測包沒有返回,就以keepaliveinterval的頻率發送,經過若干次的重試,如果探測包都沒有返回,那么就得出結論:TCP連接已經斷開,於是上面的Recv或Send調用也就能馬上返回,不會無限制地卡住了。

 

  上圖是對上面文字的說明。亮條之前,TCP處於暢通狀態,KeepAlive是以1000毫秒(keepalivetime的值)的頻率發送探測包,在發送到第32個探測包的時候,探測包沒有返回,於是就以5000毫秒(keepalivetime的值)的頻率發送探測包,重發幾次后,探測包都沒有返回,於是就得出結論:此TCP連接已經斷開了!

 

對於Win2K/XP/2003,可以從下面的注冊表項找到影響整個系統所有連接的keepalive參數:


[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters]

“KeepAliveTime”=dword:006ddd00
“KeepAliveInterval”=dword:000003e8
“MaxDataRetries”=”5″

 

  對於實用程序來說,2小時的空閑時間太長。因此,我們需要手工開啟Keepalive功能並設置合理的Keepalive參數。在XP和WIN2003系統上,可以針對單獨的socket來設置,但是在windows 2000,不能單獨設置,如果設置,那么影響是整個系統的所有socket。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM