linux網絡編程系列(五)--setsockopt的經常使用選項


1. 函數原型

  
    
  
  
   
   
            
   
   
  1. 服務器

  2. 微信

  3. 網絡

#include <sys/types.h >#include <sys/socket.h>int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
  • sockfd:標識一個套接口的描述字異步

  • level:選項定義的層次;支持SOLSOCKET、IPPROTOTCP、IPPROTOIP和IPPROTOIPV6socket

  • optname:需設置的選項,而有部分選項需在listen/connect調用前設置纔有效,這部分選項以下:SODEBUG、SODONTROUTE、SOKEEPALIVE、SOLINGER、SOOOBINLINE、SORCVBUF、SORCVLOWAT、SOSNDBUF、SOSNDLOWAT、TCPMAXSEG、TCP_NODELAYtcp

  • optval:指針,指向存放選項值的緩衝區函數

  • optlen:optval緩衝區長度性能

2. 使用場景

(1)若是在已經處於 ESTABLISHED狀態下的socket(通常由端口號和標誌符區分)調用close(socket)(通常不會當即關閉而經歷TIME_WAIT的過程)後想繼續重用該socket:flex

  
    
  
  
   
   
            
   
   
  1. spa

int reuse=1;setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)& reuse,sizeof(int));

注意:必須在調用bind函數以前設置SO_REUSEADDR選項。

(2)若是要已經處於鏈接狀態的soket在調用close(socket)後強制關閉,不經歷TIME_WAIT的過程:

  
    
  
  
   
   
            
   
   
int reuse=0;setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)& reuse,sizeof(int));

(3)在send(),recv()過程當中有時因爲網絡情況等緣由,發收不能預期進行,而設置收發時限:

  
    
  
  
   
   
            
   
   
int nNetTimeout=1000; // 1秒// 發送時限setsockopt(socketSOL_S0CKET, SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));// 接收時限setsockopt(socketSOL_S0CKET, SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));

(4)在send()的時候,返回的是實際發送出去的字節(同步)或發送到socket緩衝區的字節(異步),系統默認的狀態發送和接收一次爲8688字節(約爲8.5K);在實際的過程當中發送數據和接收數據量比較大,能夠設置socket緩衝區,而避免了send(),recv()不斷的循環收發:

  
    
  
  
   
   
            
   
   
// 接收緩衝區int nRecvBuf=32*1024; // 設置爲32Ksetsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));// 發送緩衝區int nSendBuf=32*1024; // 設置爲32Ksetsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));

注意:並非說你設置的多大,系統就會設置多大,系統通常會將咱們設置的緩衝區大小加倍,而且不得小於tcp的接收緩衝區和發送緩衝區設置的默認最小值。 注意:TCP有發送緩衝區和接收緩衝區,可是UDP由於是不可靠的,它沒有確認重傳機制,不保存應用程序數據的副本,因此是沒有發送緩衝區的,可是UDP有接收緩衝區。

(5)若是在發送數據時,但願不經歷由系統緩衝區到socket緩衝區的拷貝而影響程序的性能:

  
    
  
  
   
   
            
   
   
int nZero=0;setsockopt(socketSOL_SOCKET,SO_SNDBUF,(char *)&nZero,sizeof(int));

(6)同上在recv()完成上述功能(默認狀況是將socket緩衝區的內容拷貝到系統緩衝區):

  
    
  
  
   
   
            
   
   
int nZero=0;setsockopt(socketSOL_SOCKET,SO_RCVBUF,(char *)&nZero,sizeof(int));

(7)通常在發送UDP數據報的時候,但願該socket發送的數據具備廣播特性:

  
    
  
  
   
   
            
   
   
int bBroadcast = 1;setsockopt(s, SOL_SOCKET, SO_BROADCAST, (const char*)&bBroadcast, sizeof(int));

(8)設置存活檢測

  
    
  
  
   
   
            
   
   
int opt = 1;if (setsockopt (m_nSock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(int)) == -1){ return 0;}

(9)延遲接收 實際上就是當接收到第一個數據以後,纔會建立鏈接。對於像http這類非交互式的服務器,這個頗有意義,能夠防護空鏈接攻擊。

  
    
  
  
   
   
            
   
   
int val = 5;setsockopt(fd, SOL_TCP, TCP_DEFER_ACCEPT, &val, sizeof(val));

打開這個功能後,內核在val時間之類尚未收到數據,不會繼續喚醒進程,而是直接丟棄鏈接。 從三次握手上講,就是設置這個狀態以後,就算完成了三次握手,服務器socket狀態也不是ESTABLISHED,而依然是 SYN_RCVD,不會去接收數據。


本文分享自微信公衆號 - cpp加油站(xy13640954449)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索