socket選項自帶的TCP異常斷開檢測


TCP異常斷開是指在突然斷電,直接拔網線等等情況下,如果通信雙方沒有進行數據發送通信等處理的時候,無法獲知連接已經斷開的情況.

  在通常的情況下,為了使得socket通信不受操作系統的限制,需要自己在應用層實現心跳包機制,來檢查異常斷開的情況,一般的方式就是服務器在一段時間沒有收到客戶端數據包時,定時發包,然后客戶端回應,如果已經出現異常斷開則服務器接收會返回錯誤,而客戶端在指定時間內沒有收到數據包,則主動向服務器發包,得到錯誤就說明斷開.諸如此類的方式就是自己實現的心跳包機制.

  但操作系統本身也自帶了一些心跳包機制,這些機制是由socket的TCP棧底層實現的,不會影響應用層通信,也不需要應用層自己處理,發現異常斷開可以自行檢查出來並返回錯誤(它的本質也是在空閑時發送心跳包).以下介紹一下Windows以及linux下的方法.

  首先介紹Windows下的方法,該方式要求通信雙方必須都是Windows NT以上操作系統(如果是其它版本操作系統,如linux等等,不敢保證100%無效).MSDN中有描述WSAIoctl中的SIO_KEEPALIVE_VALS選項,該選項以及struct tcp_keepalive的定義在MSTCPiP.h有,不進行說明了,直接看代碼:

 

    #include <MSTCPiP.h>

 

    DWORD retBytes;
    tcp_keepalive inKeepSetting;
    tcp_keepalive retKeepSetting;

    inKeepSetting.onoff = 1;                //探測次數
    inKeepSetting.keepalivetime = 5500;        // 首次探測開始前的tcp無數據收發空閑時間
    inKeepSetting.keepaliveinterval = 3000;    // 每次探測的間隔時間

    if (WSAIoctl(aptSock, SIO_KEEPALIVE_VALS, 
        &inKeepSetting,
        sizeof(inKeepSetting),
        &retKeepSetting,
        sizeof(retKeepSetting),
        &retBytes,
        NULL,
        NULL) != 0)
    {
        printf("WSAIoctl Error: %d/n", WSAGetLastError());
    }

 

  Linux下的方式是通過setsockopt來設置選項,見代碼(代碼從網絡上摘錄了部分):

  #include   <netinet/tcp.h> 
  ……

 

  #define SOCKET_ERROR (-1)

 

  // 以秒為單位
  int   keepAlive = 1;       //設定KeepAlive 
  int   keepIdle = 5;        //首次探測開始前的tcp無數據收發空閑時間
  int   keepInterval = 3;  //每次探測的間隔時間
  int   keepCount = 2;     //探測次數
                
  if(setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,(void*)&keepAlive,sizeof(keepAlive)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);


  if(setsockopt(s,SOL_TCP,TCP_KEEPIDLE,(void   *)&keepIdle,sizeof(keepIdle)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);

  if(setsockopt(s,SOL_TCP,TCP_KEEPINTVL,(void   *)&keepInterval,sizeof(keepInterval)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);
                
  if(setsockopt(s,SOL_TCP,TCP_KEEPCNT,(void   *)&keepCount,sizeof(keepCount)) == SOCKET_ERROR)

      printf("Call setsockopt error, errno is %d/n", errno);


免責聲明!

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



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