setsockopt參數詳細說明(zz)

來源:互聯網
上載者:User

int setsockopt(
  SOCKET s,
  int level,
  int optname,
  const char* optval,
  int optlen
);

s(通訊端): 指向一個開啟的套介面描述字
 level:(層級): 指定選項代碼的類型。
SOL_SOCKET: 基本套介面 
IPPROTO_IP: IPv4套介面 
IPPROTO_IPV6: IPv6套介面 
IPPROTO_TCP: TCP套介面 
optname(選項名): 選項名稱 
optval(選項值): 是一個指向變數的指標 類型:整形,套介面結構, 其他結構類型:linger{}, timeval{ } 
optlen(選項長度) :optval 的大小 

傳回值:標誌開啟或關閉某個特徵的二進位選項
[/code:1:59df4ce128]

 

======================================================================== 
SOL_SOCKET 
------------------------------------------------------------------------ 
SO_BROADCAST 允許發送廣播資料 int 
適用於 UDP socket。其意義是允許 UDP socket 「廣播」(broadcast)訊息到網路上。

SO_DEBUG 允許調試 int 

SO_DONTROUTE 不尋找路由 int 

SO_ERROR 獲得通訊端錯誤 int 

SO_KEEPALIVE 保持串連 int 
檢測對方主機是否崩潰,避免(伺服器)永遠阻塞於TCP串連的輸入。 設定該選項後,如果2小時內在此套介面的任一方向都沒有資料交換,TCP就自動給對方 發一個保持存活探測分節(keepalive probe)。這是一個對方必須響應的TCP分節.它會導致以下三種情況: 對方接收一切正常:以期望的ACK響應。2小時後,TCP將發出另一個探測分節。 對方已崩潰且已重新啟動:以RST響應。套介面的待處理錯誤被置為ECONNRESET,套接 口本身則被關閉。 對方無任何響應:源自berkeley的TCP發送另外8個探測分節,相隔75秒一個,試圖得到 一個響應。在發出第一個探測分節11分鐘15秒後若仍無響應就放棄。套介面的待處理錯 誤被置為ETIMEOUT,套介面本身則被關閉。如ICMP錯誤是“host unreachable(主機不 可達)”,說明對方主機並沒有崩潰,但是不可達,這種情況下待處理錯誤被置為 EHOSTUNREACH。 

SO_DONTLINGER 若為真,則SO_LINGER選項被禁止。
SO_LINGER 延遲關閉串連 struct linger 
上面這兩個選項影響close行為
選項 間隔 關閉方式 等待關閉與否
SO_DONTLINGER 不關心 優雅 否
SO_LINGER 零 強制 否
SO_LINGER 非零 優雅 是
若設定了SO_LINGER(亦即linger結構中的l_onoff域設為非零,參見2.4,4.1.7和4.1.21各節),並設定了零逾時間隔,則closesocket()不被阻塞立即執行,不論是否有排隊資料未發送或未被確認。這種關閉方式稱為“強制”或“失效”關閉,因為套介面的虛電路立即被複位,且丟失了未發送的資料。在遠端的recv()調用將以WSAECONNRESET出錯。
若設定了SO_LINGER並確定了非零的逾時間隔,則closesocket()調用阻塞進程,直到所剩資料發送完畢或逾時。這種關閉稱為“優雅的”關閉。請注意如果套介面置為非阻塞且SO_LINGER設為非零逾時,則closesocket()調用將以WSAEWOULDBLOCK錯誤返回。
若在一個流類套介面上設定了SO_DONTLINGER(也就是說將linger結構的l_onoff域設為零;參見2.4,4.1.7,4.1.21節),則closesocket()調用立即返回。但是,如果可能,排隊的資料將在套介面關閉前發送。請注意,在這種情況下WINDOWS套介面實現將在一段不確定的時間內保留套介面以及其他資源,這對於想用所以套介面的應用程式來說有一定影響。

SO_OOBINLINE 帶外資料放入正常資料流,在普通資料流中接收帶外資料 int 

SO_RCVBUF 接收緩衝區大小 int 
設定接收緩衝區的保留大小
與 SO_MAX_MSG_SIZE 或TCP滑動視窗無關,如果一般發送的包很大很頻繁,那麼使用這個選項

SO_SNDBUF 發送緩衝區大小 int 
設定發送緩衝區的保留大小
與 SO_MAX_MSG_SIZE 或TCP滑動視窗無關,如果一般發送的包很大很頻繁,那麼使用這個選項
每個套介面都有一個發送緩衝區和一個接收緩衝區。 接收緩衝區被TCP和UDP用來將接收到的資料一直儲存到由應用進程來讀。 TCP:TCP通告另一端的視窗大小。 TCP套介面接收緩衝區不可能溢出,因為對方不允許發出超過所通告視窗大小的資料。 這就是TCP的流量控制,如果對方無視視窗大小而發出了超過宙口大小的資料,則接 收方TCP將丟棄它。 UDP:當接收到的資料報裝不進套介面接收緩衝區時,此資料報就被丟棄。UDP是沒有 流量控制的;快的寄件者可以很容易地就淹沒慢的接收者,導致接收方的UDP丟棄資料報。

SO_RCVLOWAT 接收緩衝區下限 int 
SO_SNDLOWAT 發送緩衝區下限 int 
每個套介面都有一個接收低潮限度和一個發送低潮限度。它們是函數selectt使用的, 接收低潮限度是讓select返回“可讀”而在套介面接收緩衝區中必須有的資料總量。 ——對於一個TCP或UDP套介面,此值預設為1。發送低潮限度是讓select返回“可寫” 而在套介面發送緩衝區中必須有的可用空間。對於TCP套介面,此值常預設為2048。 對於UDP使用低潮限度, 由於其發送緩衝區中可用空間的位元組數是從不變化的,只要 UDP套介面發送緩衝區大小大於套介面的低潮限度,這樣的UDP套介面就總是可寫的。 UDP沒有發送緩衝區,只有發送緩衝區的大小。

SO_RCVTIMEO 接收逾時 struct timeval 
SO_SNDTIMEO 發送逾時 struct timeval 
SO_REUSERADDR 允許重用本地地址和連接埠 int 
充許綁定已被使用的地址(或連接埠號碼),可以參考bind的man

SO_EXCLUSIVEADDRUSE
獨佔模式使用連接埠,就是不充許和其它程式使用SO_REUSEADDR共用的使用某一連接埠。
在確定多重綁定使用誰的時候,根據一條原則是誰的指定最明確則將包遞交給誰,而且沒有許可權之分,也就是說低級許可權的使用者是可以重綁定在進階許可權如服務啟動的連接埠上的,這是非常重大的一個安全隱患,
如果不想讓自己程式被監聽,那麼使用這個選項

SO_TYPE 獲得通訊端類型 int 
SO_BSDCOMPAT 與BSD系統相容 int 

========================================================================== 
IPPROTO_IP 
-------------------------------------------------------------------------- 
IP_HDRINCL 在資料包中包含IP首部 int 
   這個選項常用於駭客技術中,隱藏自己的IP地址

IP_OPTINOS IP首部選項 int 
IP_TOS 服務類型 
IP_TTL 存留時間 int 

以下IPV4選項用於組播
IPv4 選項 資料類型 描 述
  IP_ADD_MEMBERSHIP struct ip_mreq 加入到組播組中
  IP_ROP_MEMBERSHIP struct ip_mreq 從組播組中退出
  IP_MULTICAST_IF struct ip_mreq 指定提交組播報文的介面
  IP_MULTICAST_TTL u_char 指定提交組播報文的TTL
  IP_MULTICAST_LOOP u_char 使組播報文環路有效或無效
在標頭檔中定義了ip_mreq結構:
[code:1:63724de67f]
struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
};
[/code:1:63724de67f]
若進程要加入到一個組播組中,用soket的setsockopt()函數發送該選項。該選項類型是ip_mreq結構,它的第一個欄位imr_multiaddr指定了組播組的地址,第二個欄位imr_interface指定了介面的IPv4地址。
  IP_DROP_MEMBERSHIP
  該選項用來從某個組播組中退出。資料結構ip_mreq的使用方法與上面相同。
  IP_MULTICAST_IF
  該選項可以修改網路介面,在結構ip_mreq中定義新的介面。
  IP_MULTICAST_TTL
  設定組播報文的資料包的TTL(存留時間)。預設值是1,表示資料包只能在本地的子網中傳送。
  IP_MULTICAST_LOOP
  組播組中的成員自己也會收到它向本組發送的報文。這個選項用於選擇是否啟用這種狀態。

 無雙 回複於:2003-05-08 21:21:52
IPPRO_TCP 
-------------------------------------------------------------------------- 
TCP_MAXSEG TCP最大資料區段的大小 int 
擷取或設定TCP串連的最大分節大小(MSS)。傳回值是我們的TCP發送給另一端的最大 資料量,它常常就是由另一端用SYN分節通告的MSS,除非我們的TCP選擇使用一個比 對方通告的MSS小些的值。如果此值在套介面串連之前取得,則傳回值為未從另·—端 收到Mss選項的情況下所用的預設值。小於此傳回值的信可能真正用在串連上,因為譬 如說使用時間戳選項的話,它在每個分節上佔用12位元組的TCP選項容量。我們的TcP將 發送的每個分節的最大資料量也可在串連存活期內改變,但前提是TCP要支援路徑MTU 發現功能。如果到對方的路徑改變了,此值可上下調整。
TCP_NODELAY 不使用Nagle演算法 int 

指定TCP開始發送保持存活探測分節前以秒為單位的串連空閑時間。預設值至少必須為7200秒,即2小時。此選項僅在SO_KEPALIVEE套介面選項開啟時才有效。

TCP_NODELAY 和 TCP_CORK,
這兩個選項都對網路連接的行為具有重要的作用。許多UNIX系統都實現了TCP_NODELAY選項,但是,TCP_CORK則是Linux系統所專屬的而且相對較新;它首先在核心版本2.4上得以實現。此外,其他UNIX系統版本也有功能類似的選項,值得注意的是,在某種由BSD派生的系統上的TCP_NOPUSH選項其實就是TCP_CORK的一部分具體實現。
TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在這裡的含義是採用Nagle演算法把較小的包組裝為更大的幀。John Nagle是Nagle演算法的發明人,後者就是用他的名字來命名的,他在1984年首次用這種方法來嘗試解決福特汽車公司的網路擁塞問題(欲瞭解詳情請參看IETF RFC 896)。他解決的問題就是所謂的silly window syndrome ,中文稱“愚蠢視窗癥候群”,具體含義是,因為普遍終端應用程式每產生一次擊鍵操作就會發送一個包,而典型情況下一個包會擁有一個位元組的資料載荷以及40個位元組長的包頭,於是產生4000%的過載,很輕易地就能令網路發生擁塞,。 Nagle化後來成了一種標準並且立即在網際網路上得以實現。它現在已經成為預設配置了,但在我們看來,有些場合下把這一選項關掉也是合乎需要的。
現在讓我們假設某個應用程式發出了一個請求,希望發送小塊資料。我們可以選擇立即發送資料或者等待產生更多的資料然後再一次發送兩種策略。如果我們馬上發送資料,那麼互動性的以及客戶/伺服器型的應用程式將極大地受益。例如,當我們正在發送一個較短的請求並且等候較大的響應時,相關過載與傳輸的資料總量相比就會比較低,而且,如果請求立即發出那麼回應時間也會快一些。以上操作可以通過設定通訊端的TCP_NODELAY選項來完成,這樣就禁用了Nagle演算法。
另外一種情況則需要我們等到資料量達到最大時才通過網路一次發送全部資料,這種資料轉送方式有益於大量資料的通訊效能,典型的應用就是檔案伺服器。應用Nagle演算法在這種情況下就會產生問題。但是,如果你正在發送大量資料,你可以設定TCP_CORK選項禁用Nagle化,其方式正好同TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互斥的)。下面就讓我們仔細分析下其工作原理。
假設應用程式使用sendfile()函數來轉移大量資料。應用協議通常要求發送某些資訊來預先解釋資料,這些資訊其實就是前序內容。典型情況下前序很小,而且通訊端上設定了TCP_NODELAY。有前序的包將被立即傳輸,在某些情況下(取決於內部的包計數器),因為這個包成功地被對方收到後需要請求對方確認。這樣,大量資料的傳輸就會被延遲而且產生了不必要的網路流量交換。
但是,如果我們在通訊端上設定了TCP_CORK(可以比喻為在管道上插入“塞子”)選項,具有前序的包就會填補大量的資料,所有的資料都根據大小自動地通過包傳輸出去。當資料轉送完成時,最好取消TCP_CORK 選項設定給串連“拔去塞子”以便任一部分的幀都能發送出去。這同“塞住”網路連接同等重要。
總而言之,如果你肯定能一起發送多個資料集合(例如HTTP響應的頭和本文),那麼我們建議你設定TCP_CORK選項,這樣在這些資料之間不存在延遲。能極大地有益於WWW、FTP以及檔案伺服器的效能,同時也簡化了你的工作。範例程式碼如下:

intfd, on = 1;

/* 此處是建立通訊端等操作,出於篇幅的考慮省略*/

setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on)); /* cork */
write (fd, …);
fprintf (fd, …);
sendfile (fd, …);
write (fd, …);
sendfile (fd, …);

on = 0;
setsockopt (fd, SOL_TCP, TCP_CORK, &on, sizeof (on)); /* 拔去塞子 */

不幸的是,許多常用的程式並沒有考慮到以上問題。例如,Eric Allman編寫的sendmail就沒有對其通訊端設定任何選項。

Apache HTTPD是網際網路上最流行的Web伺服器,它的所有通訊端就都設定了TCP_NODELAY選項,而且其效能也深受大多數使用者的滿意。這是為什麼呢?答案就在於實現的差別之上。由BSD衍生的TCP/IP協議棧(值得注意的是FreeBSD)在這種狀況下的操作就不同。當在TCP_NODELAY 模式下提交大量小資料區塊傳輸時,大量資訊將按照一次write()函數調用發送一塊資料的方式發送出去。然而,因為負責請求交付確認的記數器是面向位元組而非面向包(在Linux上)的,所以引入延遲的機率就降低了很多。結果僅僅和全部資料的大小有關係。而 Linux 在第一包到達之後就要求確認,FreeBSD則在進行如此操作之前會等待好幾百個包。

在Linux系統上,TCP_NODELAY的效果同習慣於BSD TCP/IP協議棧的開發人員所期望的效果有很大不同,而且在Linux上的Apache效能表現也會更差些。其他在Linux上頻繁採用TCP_NODELAY的應用程式也有同樣的問題。

TCP_DEFER_ACCEPT

我們首先考慮的第1個選項是TCP_DEFER_ACCEPT(這是Linux系統上的叫法,其他一些作業系統上也有同樣的選項但使用不同的名字)。為了理解TCP_DEFER_ACCEPT選項的具體思想,我們有必要大致闡述一下典型的HTTP客戶/伺服器互動過程。請回想下TCP是如何與傳輸資料的目標建立串連的。在網路上,在分離的單元之間傳輸的資訊稱為IP包(或IP 資料報)。一個包總有一個攜帶服務資訊的包頭,包頭用於內部協議的處理,並且它也可以攜帶資料負載。服務資訊的典型例子就是一套所謂的標誌,它把包標記代表TCP/IP協議棧內的特殊含義,例如收到包的成功確認等等。通常,在經過“標記”的包裡攜帶負載是完全可能的,但有時,內部邏輯迫使TCP/IP協議棧發出只有包頭的IP包。這些包經常會引發討厭的網路延遲而且還增加了系統的負載,結果導致網路效能在整體上降低。
現在伺服器建立了一個通訊端同時等待串連。TCP/IP式的串連過程就是所謂“3次握手”。首先,客戶程式發送一個設定SYN標誌而且不帶資料負載的TCP包(一個SYN包)。伺服器則以發出帶SYN/ACK標誌的資料包(一個SYN/ACK包)作為剛才收到包的確認響應。客戶隨後發送一個ACK包確認收到了第2個包從而結束串連過程。在收到客戶發來的這個SYN/ACK包之後,伺服器會喚醒一個接收進程等待資料到達。當3次握手完成後,客戶程式即開始把“有用的”的資料發送給伺服器。通常,一個HTTP請求的量是很小的而且完全可以裝到一個包裡。但是,在以上的情況下,至少有4個包將用來進行雙向傳輸,這樣就增加了可觀的延遲時間。此外,你還得注意到,在“有用的”資料被發送之前,接收方已經開始在等待資訊了。
為了減輕這些問題所帶來的影響,Linux(以及其他的一些作業系統)在其TCP實現中包括了TCP_DEFER_ACCEPT選項。它們設定在偵聽通訊端的伺服器方,該選項命令核心不等待最後的ACK包而且在第1個真正有資料的包到達才初始化偵聽進程。在發送SYN/ACK包之後,伺服器就會等待客戶程式發送含資料的IP包。現在,只需要在網路上傳送3個包了,而且還顯著降低了串連建立的延遲,對HTTP通訊而言尤其如此。
這一選項在好些作業系統上都有相應的對等物。例如,在FreeBSD上,同樣的行為可以用以下代碼實現:

/* 為明晰起見,此處略去無關代碼 */
struct accept_filter_arg af = { "dataready", "" };
setsockopt(s, SOL_SOCKET, SO_ACCEPTFILTER, &af, sizeof(af));
這個特徵在FreeBSD上叫做“接受過濾器”,而且具有多種用法。不過,在幾乎所有的情況下其效果與TCP_DEFER_ACCEPT是一樣的:伺服器不等待最後的ACK包而僅僅等待攜帶資料負載的包。要瞭解該選項及其對高效能Web伺服器的重要意義的更多資訊請參考Apache文檔上的有關內容。
就HTTP客戶/伺服器互動而言,有可能需要改變客戶程式的行為。客戶程式為什麼要發送這種“無用的”ACK包呢?這是因為,TCP協議棧無法知道ACK包的狀態。如果採用FTP而非HTTP,那麼客戶程式直到接收了FTP伺服器提示的資料包之後才發送資料。在這種情況下,延遲的ACK將導致客戶/伺服器互動出現延遲。為了確定ACK是否必要,客戶程式必須知道應用程式協議及其目前狀態。這樣,修改客戶行為就成為必要了。
對Linux客戶程式來說,我們還可以採用另一個選項,它也被叫做TCP_DEFER_ACCEPT。我們知道,通訊端分成兩種類型,偵聽通訊端和串連通訊端,所以它們也各自具有相應的TCP選項集合。因此,經常同時採用的這兩類選項卻具有同樣的名字也是完全可能的。在串連通訊端上設定該選項以後,客戶在收到一個SYN/ACK包之後就不再發送ACK包,而是等待使用者程式的下一個發送資料請求;因此,伺服器發送的包也就相應減少了。

TCP_QUICKACK

阻止因發送無用包而引發延遲的另一個方法是使用TCP_QUICKACK選項。這一選項與 TCP_DEFER_ACCEPT不同,它不但能用作管理串連建立過程而且在正常資料轉送過程期間也可以使用。另外,它能在客戶/伺服器串連的任何一方設定。如果知道資料不久即將發送,那麼延遲ACK包的發送就會派上用場,而且最好在那個攜帶資料的資料包上設定ACK 標誌以便把網路負載減到最小。當發送方肯定資料將被立即發送(多個包)時,TCP_QUICKACK選項可以設定為0。對處於“串連”狀態下的通訊端該選項的預設值是1,首次使用以後核心將把該選項立即複位為1(這是個一次性的選項)。
在某些情形下,發出ACK包則非常有用。ACK包將確認資料區塊的接收,而且,當下一塊被處理時不至於引入延遲。這種資料轉送模式對互動過程是相當典型的,因為此類情況下使用者的輸入時刻無法預測。在Linux系統上這就是預設的通訊端行為。
在上述情況下,客戶程式在向伺服器發送HTTP請求,而預先就知道請求包很短所以在串連建立之後就應該立即發送,這可謂HTTP的典型工作方式。既然沒有必要發送一個純粹的ACK包,所以設定TCP_QUICKACK為0以提高效能是完全可能的。在伺服器方,這兩種選項都只能在偵聽通訊端上設定一次。所有的通訊端,也就是被接受呼叫間接建立的通訊端則會繼承原有通訊端的所有選項。
通過TCP_CORK、TCP_DEFER_ACCEPT和TCP_QUICKACK選項的組合,參與每一HTTP互動的資料包數量將被降低到最小的可接受水平(根據TCP協議的要求和安全方面的考慮)。結果不僅是獲得更快的資料轉送和請求處理速度而且還使客戶/伺服器雙向延遲實現了最小化。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.