套接口選項

設置和影響套接口選項的方法有
1.getsockopt和setsockopt
2.fcntl
3.ioctl

 

getsockopt和setsockopt
這兩個方法僅適用於套接字
有兩種基本類型的套接口選項:打開或關閉某個特性的二進制標誌,取得並返回咱們能夠設置或檢驗的特定值的選項,標有標誌的列指明是否爲標誌選項,對於這些項,0表示關閉標誌,非0表示打開標誌。

 

 

 並非全部的系統的套接字都支持全部的選項,必要時候自行驗證一番。linux

 

套接字的不支持分爲兩種
1.未實現相關的定義,好比SO_REUSEPORT宏未定義
2.定義了名字,但並不支持,好比SO_REUSEPORT雖然定義,調用getsockopt卻會報錯。

 

針對這兩種不支持的測試
1.#ifdef   #else   #endif
2.getsockopt返回失敗或者取回的值爲空。

 

套接口選項應該何時設置
抽取redis的一段代碼來示例
//監聽套接字接收accept事件的處理器
acceptTcpHandler
{
//accept的包裹函數
anetTcpAccept
//設置socket的選項:設置非阻塞;禁用Nagle算法;設置keepalive
acceptCommonHandler
}
某些設置要更早一些,好比SO_RCVBUF和SO_SNDBUF,須要在服務器的監聽套接口上設置,或者在未connect的客戶端套接口上設置。

 

 

 

套接口基本選項
基本選項是協議無關的,但有些選項只能應用於特定類型的套接口中

 

SO_BROADCAST
此選項禁止或使能進程發送套接口廣播的能力。只有數據報套接口支持廣播,還必須是支持廣播的網絡。你不可能在一個點對點網絡上發起廣播。

 

SO_DEBUG
僅有TCP支持,當打開時,內核對TCP在此套接口上的發送和接收消息都作詳細跟蹤,這些信息保存在內核緩衝區,由程序trpt進行檢查。

 

SO_ERROR
當套接口發生錯誤時,套接口名爲so_error的變量被設置爲標準的UNIX Exxx值的一個,它稱爲套接字的待處理錯誤。
內核能夠經過select等多路複用I/O當即通知調用進程,進程能夠經過SO_ERROR選項獲取so_error的值,so_error隨後由內核恢復爲0.
當進程調用read且沒有數據返回時,若是so_error爲非0值,則read返回-1且errno設置爲so_error的值,so_error隨後復位爲0.若是此套接口上有數據排隊,則read返回那些數據,而不是返回錯誤條件。
若是在進程調用write時,so_error爲非0值,則write返回-1值,而且errno設置爲so_error的值,so_error也被複位爲0.

 

SO_KEEPALIVE
給TCP一個保存存活選項之後,若是2個小時內此套接口的任何一方都沒有數據交換。TCP就自動給對方發送一個保持存活探測分節,這是一個必須回覆的TCP分節,它會致使如下三種狀況:
1.對方回覆一個正常的ACK,應用進程得不到任何通知(由於一切正常)。
2.對方以RST響應,它告訴本地TCP,對方已崩潰而且從新啓動,套接口的待處理錯誤被設置成ECONNRESET,套接口自己被關閉。
3.對方對保持存活分節無任何響應,源自berkeley的TCP將發送另外8個分節,每隔75s一個,試圖獲得響應,若是對TCP的探測存活分節沒有響應,套接口的錯誤被設置成ETIMEOUT,套接字自己被關閉。但若是收到某個ICMP的錯誤,則返回相應的錯誤。
主要是檢測對方主機是否崩潰,若是對方進程崩潰,它的TCP將跨鏈接發送一個FIN,這能夠經過多路複用檢測到。
全部的TCP探測分節均無響應,也不意味這鏈接已中斷,也有多是某個中間路由器暫時性的有問題,也就有可能關閉一個有效鏈接。
這個選項通常由服務器使用,由於若是客戶主機崩潰,服務器將永遠不知道,並繼續等待不會到來的輸入,這稱爲半打開鏈接,保持存活消息將檢測這些鏈接並終止它們。
當TCP對端發生某些事件必須檢測時的一些手段

 

 

 

SO_LINGER選項
只是函數close對面向鏈接的套接字如何操做,缺省設置是當即返回,若是有數據殘留在套接口發送緩衝區,系統試着將這些數據發送給對端。
SO_LINGER可使咱們改變這些缺省操做。SO_LINGER的主要做用是去掉TIME_WAIT狀態,使重啓服務器進程是夠從新綁定端口。做爲替代,咱們能夠在bind的時候使用SO_REUSERADDR選項。
SO_LINGER的另外一個做用是,告訴咱們發送的數據和FIN已由對方TCP確認,它並不能告訴咱們對方應用進程是否讀取了數據,若是不設置該選項,咱們連對方是否接收了數據都不知道。
close的缺省操做,當即返回

 

 

 設置了SO_LINGER,而且l_linger爲正值時的closeredis

 

 

 

讓客戶知道服務器已讀其數據的一個方法是:調用SHUT_WR的shutdown,並等待對方close鏈接的本地端。  
使客戶端知道服務器已讀其數據的另外一個方式是:使用應用級的ACK。

 

 

 

SO_RCVBUF和SO_SNDBUF
每個套接口都有一個接收緩衝區和一個發送緩衝區
接收緩衝區被TCP和UDP用來保存收到的數據,一直保存到應用程序來讀。對於TCP來講,接收緩衝區的大小就是告知對方的窗口大小。TCP套接口接收緩衝區不可能溢出,由於對方不可能發出超出所通告窗口大小的數據,這就是TCP的流量控制。若是對方無視窗口大小而發出了超出窗口大小的數據,則接收方TCP將丟棄它。對於UDP來講,若是接收到的數據裝不進套接口緩衝區時,將會丟棄它。UDP是沒有流量控制的,快的發送方能夠輕易的淹沒慢的接受者。 這致使接收方的UDP丟棄數據報。
當設置TCP套接字緩衝區大小時,函數調用順序很是重要。TCP的窗口規模是在創建鏈接時用SYN交換來的,對於客戶來講,必須在connect以前設置,對於服務器來講,意味着調用listen以前必須給監聽套接字設置緩存區大小。給已鏈接的套接字設置該選項可能沒有任何影響。
TCP套接字緩衝區的大小至少是MSS的三倍,而且必須是MSS的偶數倍,由於客戶TCP必須爲客戶數據保存一份拷貝,直至接收到對端的確認。
fpathconf獲取套接字緩衝區的上限。

 

SO_RCV_LOWAT和SO_SNDLOWAT
每一個套接口也都有一個發送低潮限度和一個接收低潮限度。
接收低潮限度是在多路複用API返回可讀時,套接口接收緩衝區至少有的數據量。對於TCP和UDP,缺省值爲1.
發送低潮限度是在多路複用API返回可寫時,套接口發送緩衝區至少有的可用空間。對於TCP套接字,其值常缺省爲2048.UDP沒有發送緩衝區,只有發送緩衝區大小,對於UDP來講,只要發送緩衝區大小大於套接口的低潮限度,UDP套接口就老是可寫的。

 

SO_RCVTIMEO和SO_SNDTIMEO
給套接字設置一個接收和發送超時,缺省超時是禁止的。
接收超時影響:read、readv、recvfrom、recv和recvmsg
發送超時影響:write、writev、send、sendto和sendmsg。

 

 

 

SO_REUSEADDR和SO_REUSEPORT
SO_REUSEADDR一般爲如下4個目的服務
1.SO_REUSEADDR容許啓動一個監聽服務器並綁定其衆所周知端口,哪怕之前創建的將此端口用做本地端口的鏈接仍然存在。
2.SO_REUSERADDR容許在一個端口上啓動同一個服務器的不一樣實例,只要每一個實例綁定一個不一樣的本地IP地址便可。
3.SO_REUSEADDR容許單個進程捆綁同一端口到多個套接字,只要每一個套接字捆綁不一樣的本地IP端口。
4.SO_REUSEADDR還容許徹底重複的綁定,當一個IP和端口捆綁到一個套接字時,容許把同一個IP和端口捆綁到另外一個套接字。通常來講,這個特性僅在支持多播的系統上纔有,並且僅對UDP套接字(TCP不支持多播)。這個做用並非每一個系統都支持。

 

TCP套接口選項
TCP_KEEPALIVE
因爲SO_KEEPALIVE的超時時間是2小時,而且難以修改,在linux上一般還會設置TCP_KEEPALIVE,設置TCP_KEEPALIVE僅在SO_KEEPALIVE套接口選項打開時纔有效。

 

 

TCP_NODELAY
禁止TCP的nagle算法,缺省時,該功能是打開的。
Nagle算法:若是給定TCP鏈接上有待確認的分組,則直到現有數據被確認前,不往TCP上發送任何小分組。小分組即小於MSS的分組。若是可能,TCP老是發送最大大小的分組;Nagle算法的目的是防止TCP鏈接上有待確認的小分組存在。
Nagle算法常與另外一個TCP算法一塊兒使用,延滯ACK算法,此算法致使在接收到數據時不當即發送ACK。而是由TCP等待一小段時間(50-200ms)才發出ACK,所但願的是這段時間TCP有數據回覆給對端,這樣ACK能夠捎帶在這些數據上。又是就節省了一個TCP分節。
不適合Nagle和延滯ACK的客戶端:以若干小數據分片發送單個邏輯請求給服務器的客戶。對這類客戶的修復辦法是
1.使用writev合併小數據分片爲完整的邏輯請求,而後發送
2.拷貝屬於單個邏輯的多個小數據分片到一個緩衝區,而後完整發送
3.設置TCP_NODELAY並繼續調用write兩次。

 fcntl函數算法

 

 

fcntl、ioctl和路由套接口操做小結
從表中來看,posix推薦使用fcntl
相關文章
相關標籤/搜索