有很多方法來獲取和設(shè)置影響套接口的選項:
這兩個函數(shù)僅用于套接口。
#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t *optlen);返回值:0——成功,-1——出錯
其中,
sockfd必須指向一個打開的套接口描述字;
level(級別)指定系統(tǒng)中解釋選項的代碼:或為通用套接口代碼,或為某個特定于協(xié)議的代碼(例如ipv4、IPv6、TCP或SCTP)。
optval是一個指向變量(*optval)的指針,setsockopt從*optval中取得選項待設(shè)置的新值,getsockopt則把已獲取的選項當(dāng)前值存放到*optval中。
optlen指定*optval的大小,它對于setsockopt是一個值參數(shù),對于getsockopt是一個值-結(jié)果參數(shù)。
套接口選項粗分為兩大基本類型:
(1)標(biāo)志選項:開啟或禁止某個特性的二元選項。
(2)值選項:取得并返回我們可以設(shè)置或檢查的特定值的選項。
*optval的值為0表示禁止選項,不為0表示開啟選項。
fcntl函數(shù)提供了與網(wǎng)絡(luò)編程相關(guān)的如下特性:
#include <fcntl.h>int fcntl(int fd, int cmd, ... /* int arg */);返回值:依賴于cmd參數(shù)——成功,-1——出錯
每種描述字(包括套接口描述字)都有一組由F_GETFL命令獲取或由F_SETFL命令設(shè)置的文件標(biāo)志。其中影響套接口描述字的兩個標(biāo)志是:
O_NONBLOCK 非阻塞I/O
O_ASYNC 信號驅(qū)動I/O
注意
設(shè)置某個文件狀態(tài)標(biāo)志的唯一正確的方法是:先取得當(dāng)前標(biāo)志,與新標(biāo)志邏輯或后再設(shè)置標(biāo)志。例如,使用fcntl開啟非阻塞I/O的典型代碼是:
int flags;if( (flags = fcntl(fd, F_GETFL, 0)) < 0) err_sys("F_GETFL error");flags |= O_NONBLOCK;if(fcntl(fd, F_SETFL, flags) < 0) err_sys("F_SETFL error");
信號SIGIO和SIGURG與其他信號的不同之處在于,這兩個信號僅在已使用F_SETOWN命令給相關(guān)套接口指派了屬主后才會產(chǎn)生。
F_SETOWN命令的整數(shù)類型arg參數(shù)既可以是一個正整數(shù),指出接收信號的進(jìn)程ID,也可以是一個負(fù)整數(shù),其絕對值指出接收信號的進(jìn)程組ID。
F_GETOWN命令把套接口屬主作為fcntl函數(shù)的返回值返回,它既可以是進(jìn)程ID(一個正的返回值),也可以是進(jìn)程組ID(一個除-1以外的負(fù)值)。
指定接收信號的套接口屬主為一個進(jìn)程或一個進(jìn)程組的差別在于:前者僅導(dǎo)致單個進(jìn)程接收信號,而后者則導(dǎo)致整個進(jìn)程組中的所有進(jìn)程(也許不止一個進(jìn)程)接收信號。
使用socket函數(shù)新創(chuàng)建的套接口并沒有屬主。然而如果一個新的套接口是從一個監(jiān)聽套接口創(chuàng)建來的,那么套接口屬主將由已連接套接口從監(jiān)聽套接口繼承而來。
SO_KEEPALIVE
給一個TCP套接口設(shè)置保持存活(keep-alive)選項后,如果2小時內(nèi)在該套接口的任一方向上都沒有數(shù)據(jù)交換,TCP就自動給對端發(fā)送一個保持存活探測分節(jié)(keep-alive PRobe)。這是一個對端必須響應(yīng)的分節(jié)。
本選項的目的是檢測對端主機(jī)是否崩潰或變得不可達(dá)。
本選項一般由服務(wù)器使用,不過客戶也可以使用。
服務(wù)器使用本選項是因為它們花大部分時間阻塞在等待穿越TCP連接的輸入上,也就是說在等待客戶的請求。然而如果客戶主機(jī)連接掉線、電源掉電或系統(tǒng)崩潰,服務(wù)器進(jìn)程將永遠(yuǎn)不會知道,并將繼續(xù)等待永遠(yuǎn)不會到達(dá)的輸入。我們稱這種情況為半開連接(half-open connection)。保持存活選項將檢測出這些半開連接并終止它們。
SO_RCVBUF、SO_SNDBUF
每個TCP套接口和SCTP套接口都有一個發(fā)送緩沖區(qū)和一個接收緩沖區(qū),每個UDP套接口都有一個接收緩沖區(qū)。SO_SNDBUF和SO_RCVBUF套接口選項允許我們改變這些緩沖區(qū)的大小。對于客戶,SO_RCVBUF選項必須在調(diào)用connect之前設(shè)置;對于服務(wù)器,SO_RCVBUF選項必須在調(diào)用listen之前給監(jiān)聽套接口設(shè)置。
SO_REUSEADDR
SO_REUSEADDR套接口選項為以下四個不同的目的提供服務(wù):
(1)SO_REUSEADDR允許啟動一個監(jiān)聽服務(wù)器并捆綁其眾所周知端口,即使以前建立的將該端口用作它們的本地端口的連接仍存在。
(2)SO_REUSEADDR允許在同一端口上啟動對同一服務(wù)器的多個實例,只要每個實例捆綁一個不同的本地IP地址即可。
(3)SO_REUSEADDR允許單個進(jìn)程捆綁同一端口到多個套接字上,只要每次捆綁指定不同的本地IP地址即可。
(4)SO_REUSEADDR允許完全重復(fù)的綁定:當(dāng)一個IP地址和端口已綁定到某個套接口上時,如果傳輸協(xié)議支持,同樣的IP地址和端口可以捆綁到另一個套接口上。一般來說,本特性只支持UDP套接口。
所有TCP服務(wù)器都應(yīng)指定SO_REUSEADDR選項。
新聞熱點
疑難解答