Socket選項的那些事(一)

Socket選項的那些事(一)

今天跟大家分享套接字選項的一些事情,以下就是要詳細介紹的東西,通過實際的編程來分享這些東西,有什麼問題或者錯誤歡迎來討論哈!!!!!

  • SOL_SOCKET協議族選項(通用地址族選項)
  • IPPROTO_ TCP和IPPROTO_ IP選項
  • ioctl()函數

OK,進入我們今天的分享,先來講述SOL_SOCKET協議族選項(通用地址族選項)

獲取和設置套接字選項

其實在進行網絡編程的時候,我們需要經常去查看並且設置套接字的某些特性。例如我們想去設置地址複用,設置讀寫數據的超時時間,想對讀寫緩衝區的大小進行調整,其中獲得套接字的選項就是getsckopt()函數,那麼對應話設置套接字的選項就是sesockopt()函數

介紹一下它們兩個

#include<sys/socket.h>

int getsockopt(int s,int level,int optname,void* optval.socklen_t* optlen);
int setsockopt(int s,int level,int optname,void* optval.socklen_t optlen);

用來獲取和設置某個套接字相關的選項,選項可能存在於多層協議中,他們總會出現在最上面的套接字層。當對套接字選項進行操作的時候,我們必須給出選項所在的層次與名稱,爲了操作套接字層的選項,應該將層的值指定爲SOL_SOCKET,爲了控制其它層的選項,必須給出控制選項的協議類型號。

我們來介紹上面兩個函數參數的含義

  • s:表示將要獲取和設置的套接字描述符
  • level:表示層次
  • optname:表示選項名
  • optval:表示操作的內存緩衝區
  • optlen:表示optval的長度

對於getsockopt,指向用於獲取返回值的緩衝區,setsockopt指向設置參數的緩衝區。optval表示第optval的長度。getsockopt,指向socklen_t類型的指針,當用於傳入參數時,表示傳入optval的實際長度。當用於傳出參數時,表示用於保存optval的最大長度。

當用於傳出參數時,表示用於保存optval的最大長度。對於setopt函數,optlen表示第四個參數實際的長度,在函數執行成功的時候返回值爲0,函數執行失敗時返回爲-1。同時我們可以根據錯誤代碼來判斷錯誤類型。

getsockopt()函數和setsocktopt()函數錯誤的代碼含義:

  • EBADF:參數s不是有效的文件描述符
  • EFAULT:optval指向的內存並非有效的進程空間
  • EINVAL:在調用setsockopt()函數時,optlen無效
  • ENOPROTOOPT:指定的協議層不能識別選項
  • ENOTSOCK:s描述的不是套接字的描述符

按照參數level值的不同,套接字選項可以分爲三大類:

  • 通用套接選項:level的值爲SOL_SOCKET
  • IP選項:level的值爲IPPROTO_IP
  • TCP選項:level的值爲IPPROTO_TCP

SO_KEEPALIVE選項

SO_KEEPALIVE保持連接選項,2小時沒有數據交互,發送探測報文,有三種迴應:

  • 迴應一個ACK報文
  • 迴應一個RST報文
  • 沒有回任何迴應

使用方法:

就是調用setsockopt進行設置

int optval =1; 
setsockopt(sockfd,SOL_SOCKET,SO_KEEPALIVE,&optval,sizeof(optval));

第二個參數表示通用地址族選項,第三個就表示KEEPALIVE選項

SO_LINGER選項

SO_LINGER緩衝區處理方式選項,主要用於設置TCP連接關閉時的行爲方式,它的操作通過一個結構體進行:

struct linger{
int l_onoff; //  開啓(非0)關閉(0
int l_linger; //停留時間
};

根據以上結構體的不同,close調用可能產三種行爲

我們介紹一下產生三種行爲的不同方式:

  • l_ onoff等於0,此時SO_ LINGER不起作用,close用默認行爲來關閉套接字
  • l_ onoff不爲0,l_ linger爲0,close系統調用立即返回,TCP將丟棄發送緩衝區中的殘留數據,同時給對方發送一個復位報文段
  • l_ onoff不爲0,l_ linger不爲0,那麼這個時候close的行爲取決於兩個條件,第一個條件是被關閉的套接字中的發送緩衝區中是否還有殘留的數據,第二個條件就是該套接字是阻塞的還是飛阻塞的。對於阻塞的來說close將等待。如果是非阻塞的將會立即返回。

使用方法:

optval.l_onoff =1;
optval.l_linger =60; 
setsockopt(sockfd,SOL_SOCKET,SO_LINGER,&optval,sizeof(optval));

設置兩個參數,然後進行set設置即可。

SO_ RECVBUF和SO_ SNDBUF選型

用於操作發送緩衝區和接收緩衝區的大小,使用的時候我們需要注意兩點。

  • 設置TCP/UDP連接的接收/發送緩衝區的含義:在UDP連接中他是無連接,發送緩衝區在數據通過網絡發送後就可以丟棄不用保存,而接收緩衝區就需要保存數據,直到客戶端進行讀取,由於UDP沒有流量控制,當緩衝區過小時發送端局部時間內會產生爆發性數據傳輸,因此在使用UDP時,需要將接收緩衝區設置爲比較大的值。而在TCP連接中,接收緩衝區的大小,就是滑動窗口的大小,TCP的接收緩衝區不可能溢出,因爲它不允許對方發送超過緩衝區大小的數據
  • 在connect()函數調用之前設置:因爲接收緩衝區的大小與滑動窗口的大小是一致的,而滑動窗口的協商是在建立連接的時候通過同步報文獲得的。對於客戶端來說,接收緩衝區的大小要在connnect系統調用前進行設置,因爲connect需要通過同步報文段建立連接,而對於服務器來說,需要在listen之前進行接收緩衝區的大小設置。因爲accept函數的返回值是繼承了listen描述符屬性

SO_ RCVLOWAT和SO_ SNDLOWAT選選型

SO_ RCVLOWAT表示接收超時,SO_ SNDLOWAT表示發送超時,設置是通過一個結構體實現的。

struct  timeval{
   time_t tv_sec;
   sseconds_t tv_usec;
};

SO_ RCVTIMEO和SO_ SNDTIMEO選項

SO_ RCVTIMEO和SO_ SNDTIMEO選項表示TCP接收緩衝區和發送緩衝區的低水位標記,它們一般會被I/O系統複用調用,來判斷socket是否可讀或者可寫。

SO_REUSEADDR選項

表示可以重複使用本地地址和端口嗎,這個設置在服務器端經常被使用。設置了SO_ REUSEADDR地址可重用選項,設置此選項可以使用被處於TIME_WAIT狀態的連接佔用的socket地址:

比如說某個服務器進程佔用了TCP服務器的80端口。當再次監聽的時候會返回錯誤。設置了此選項可以解決這個問題。也就是可以共用這個端口。有的時候,我們經常會遇到,當我們非正常退出的時候,這個端口會過一段時間內核纔會釋放,或者很久都沒有被釋放,我們無法再次開啓服務器,設置了此選項就可以很好的解決這個問題了。

此選項的實際編程演示:

int sock = socket(AF_INET,SOCK_STREAM,0);
assert(sock >=0);
int reuse = 1;

//設置SO_REUSEADDR可複用選項
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse));


//服務器的長用結構設置
struct sockaddr_in address;
bzero(&address,sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET,ip,&address.sin_addr);
address.sin_port = htons(port);
int ret = bind(sock,(struct sockaddr*)&address,sizeof(address));

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章