C/C++網路編程中的TCP保活

來源:互聯網
上載者:User

在預設的情況下,TCP串連是沒有保活的心跳的。這就是說,當一個TCP的socket,用戶端與服務端誰也不發送資料,會一直保持著串連。這其中如果有一方異常掉線,另一端永遠也不可能知道。這對於一些服務型的程式來說,將是災難性的後果。

  所以,必須對建立的socket,啟用保活心跳,即Keepalive選項。

啟用Keepalive

  對於WIN32或者Linux平台來說,設定socket的Keepalive都很簡單,只需使用setsockopt設定SO_KEEPALIVE即可。

  setsockopt的函數原型在Linux環境下為:

[html]
view plaincopy

  1. #include <sys/types.h>    
  2. #include <sys/socket.h>    
  3.     
  4. int setsockopt(int s, int level, int optname,    
  5.                const void *optval,    
  6.                socklen_t optlen);    

,在WIN32平台下為

[html]
view plaincopy

  1. #include <winsock2.h>    
  2.     
  3. int setsockopt(int s, int level, int optname,    
  4.                const char *optval,    
  5.                int optlen);    

  因為const void *可以接受const char *型的參數,所以為了代碼的跨平台編譯考慮,可以採用以下代碼來設定TCP的Keepalive選項。

[html]
view plaincopy

  1. alive = 1;  
  2. if (setsockopt  
  3.     (fd, SOL_SOCKET, SO_KEEPALIVE, (const char *) &alive,  
  4.      sizeof alive) != 0)  
  5.   {  
  6.     log_warn ("Set keep alive error: %s.\n", strerror (errno));  
  7.     return -1;  
  8.   }  

  這樣,對於TCP的串連,就啟用了系統預設值的保活心跳。

Linux環境下的TCP Keepalive參數設定

  為什麼說是系統預設值的呢?因為有這樣幾個值,我們並沒有手動設定,是採用的系統預設值。即,

  1. 多長時間發送一次保活心跳?
  2. 如果沒有返回,多長時間再重試發送?
  3. 重試幾次為失敗?

      如果是Linux作業系統,這三個值分別為

    [html]
    view plaincopy
    1. # cat /proc/sys/net/ipv4/tcp_keepalive_time    
    2. 7200    
    3. # cat /proc/sys/net/ipv4/tcp_keepalive_intvl    
    4. 75    
    5. # cat /proc/sys/net/ipv4/tcp_keepalive_probes    
    6. 9    

  這就是說,在Linux系統下,如果對於TCP的socket啟用了Keepalive選項,則會在7200秒(即兩個小時)沒有資料後,發起KEEPALIVE報文。如果沒有回應,則會在75秒後再次重試。如果重試9次均失敗,則認定串連已經失效。TCP的讀取操作,將返回0。

  這對於我們大多數應用來說,前兩個時間值都有點太長了。

  我們可以通過重設上面三個值,來使得作業系統上啟動並執行所有啟用了Keepalive選項的TCP的socket的行為更改。

  我們也可以只針對我們自己建立的socket,重設這三個值。它們分別對應TCP_KEEPIDLE、TCP_KEEPINTL和TCP_KEEPCNT的選項值,同樣可以使用setsockopt進行設定。

[html]
view plaincopy

  1. #include <stdlib.h>    
  2. #include <fcntl.h>    
  3. #include <errno.h>    
  4. #include <sys/socket.h>    
  5. #include <netinet/tcp.h>    
  6. #include <netinet/in.h>    
  7. #include <netdb.h>    
  8. #include <arpa/inet.h>    
  9.     
  10. int    
  11. socket_set_keepalive (int fd)    
  12. {    
  13.   int ret, error, flag, alive, idle, cnt, intv;    
  14.     
  15.   /* Set: use keepalive on fd */    
  16.   alive = 1;    
  17.   if (setsockopt    
  18.       (fd, SOL_SOCKET, SO_KEEPALIVE, &alive,    
  19.        sizeof alive) != 0)    
  20.     {    
  21.       log_warn ("Set keepalive error: %s.\n", strerror (errno));    
  22.       return -1;    
  23.     }    
  24.     
  25.   /* 10秒鐘無資料,觸發保活機制,發送保活包 */    
  26.   idle = 10;    
  27.   if (setsockopt (fd, SOL_TCP, TCP_KEEPIDLE, &idle, sizeof idle) != 0)    
  28.     {    
  29.       log_warn ("Set keepalive idle error: %s.\n", strerror (errno));    
  30.       return -1;    
  31.     }    
  32.     
  33.   /* 如果沒有收到回應,則5秒鐘後重發保活包 */    
  34.   intv = 5;    
  35.   if (setsockopt (fd, SOL_TCP, TCP_KEEPINTVL, &intv, sizeof intv) != 0)    
  36.     {    
  37.       log_warn ("Set keepalive intv error: %s.\n", strerror (errno));    
  38.       return -1;    
  39.     }    
  40.     
  41.   /* 連續3次沒收到保活包,視為串連失效 */    
  42.   cnt = 3;    
  43.   if (setsockopt (fd, SOL_TCP, TCP_KEEPCNT, &cnt, sizeof cnt) != 0)    
  44.     {    
  45.       log_warn ("Set keepalive cnt error: %s.\n", strerror (errno));    
  46.       return -1;    
  47.     }    
  48.     
  49.   return 0;    
  50. }    
WIN32環境下的TCP Keepalive參數設定

  而WIN32環境下的參數設定,就要麻煩一些,需要使用另外的一個函數WSAIoctl和一個結構struct tcp_keepalive。

  它們的原型分別為:

[html]
view plaincopy

  1. #include <winsock2.h>    
  2. #include <mstcpip.h>    
  3.     
  4. int WSAIoctl(    
  5.              SOCKET s,    
  6.              DWORD dwIoControlCode,    
  7.              LPVOID lpvInBuffer,    
  8.              DWORD cbInBuffer,    
  9.              LPVOID lpvOutBuffer,    
  10.              DWORD cbOutBuffer,    
  11.              LPDWORD lpcbBytesReturned,    
  12.              LPWSAOVERLAPPED lpOverlapped,    
  13.              LPWSAOVERLAPPED_COMPLETION lpCompletionRoutine    
  14. );    
  15.     
  16. struct tcp_keepalive {    
  17.     u_long onoff;    
  18.     u_long keepalivetime;    
  19.     u_long keepaliveinterval;    
  20. };    

  在這裡,使用WSAIoctl的時候,dwIoControlCode要使用SIO_KEEPALIVE_VALS,lpvOutBuffer用不上,cbOutBuffer必須設定為0。

  struct tcp_keepalive結構的參數意義為:

  onoff,是否開啟KEEPALIVE; keepalivetime,多長時間觸發Keepalive報文的發送; keepaliveinterval,多長時間沒有回應觸發下一次發送。

  注意:這裡兩個時間單位都是毫秒而不是秒。

[html]
view plaincopy

  1. #include <winsock2.h>    
  2. #include <mstcpip.h>    
  3.     
  4. int    
  5. socket_set_keepalive (int fd)    
  6. {    
  7.   struct tcp_keepalive kavars[1] = {    
  8.       1,    
  9.       10 * 1000,        /* 10 seconds */    
  10.       5 * 1000          /* 5 seconds */    
  11.   };    
  12.     
  13.   /* Set: use keepalive on fd */    
  14.   alive = 1;    
  15.   if (setsockopt    
  16.       (fd, SOL_SOCKET, SO_KEEPALIVE, (const char *) &alive,    
  17.        sizeof alive) != 0)    
  18.     {    
  19.       log_warn ("Set keep alive error: %s.\n", strerror (errno));    
  20.       return -1;    
  21.     }    
  22.     
  23.   if (WSAIoctl    
  24.       (fd, SIO_KEEPALIVE_VALS, kavars, sizeof kavars, NULL, sizeof (int), &ret, NULL,    
  25.        NULL) != 0)    
  26.     {    
  27.       log_warn ("Set keep alive error: %s.\n", strerror (WSAGetLastError ()));    
  28.       return -1;    
  29.     }    
  30.     
  31.   return 0;    
  32. }  

原文地址:http://blog.csdn.net/weiqubo/article/details/7225338

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.