歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> 套接口選項

套接口選項

日期:2017/2/27 14:18:53   编辑:更多Linux
  獲取和設置影響套接口選項的函數: getsockopt :獲取套接口選項 setsockopt: 獲取套接口選項 fcntl: 設置套接口為非阻塞I/O型信號驅動I/O型等 oictl 套接口選項 SO-KEEPALIVE SO-LINGER SE-RCVBUF 和 SO-SNDBUF SO-RCVWAT和 SO-SNDLOWAT SO-RCVTIMEO和 SO-SNDTIMEO SO-REUSEADDR和 SO-REUSPORT IP-TTL TCP-KEEPALIVE -------------------------------------------------------------------------------- getsockopt 和 setsockopt 獲得套接口選項: int getsockopt ( int sockfd, int level, int optname, void * optval, socklen_t *opteln ) 設置套接口選項: int setsockopt ( int sockfd, int level, int optname, const void * optval, socklen_t *opteln ) sockfd(套接字): 指向一個打開的套接口描述字 level:(級別): 指定選項代碼的類型。 SOL_SOCKET: 基本套接口 IPPROTO_IP: IPv4套接口 IPPROTO_IPV6: IPv6套接口 IPPROTO_TCP: TCP套接口 optname(選項名): 選項名稱 optval(選項值): 是一個指向變量的指針 類型:整形,套接口結構, 其他結構類型:linger{}, timeval{ } optlen(選項長度) :optval 的大小 返回值:標志打開或關閉某個特征的二進制選項 -------------------------------------------------------------------------------- 檢查套接口選項的程序 輸出套接口的選項: 定義感興趣的套接口選項 調用getsockopt 輸出套接口選項 定義聯合:不同的套接口選項有不同類型 union val { //套接口選項可能有的5個類型分別作為一個成員: int i_val; long l_val; char c_val[10]; strUCt linger linger_val; struct timeval timeval_val; //struct {int S; int uS} } val; //函數原型(prototype),這些函數用於輸出套接口選項的值 static char *sock_str_flag(union val *, int); //靜態函數,只可在本文件中被調用 static char *sock_str_int(union val *, int); static char *sock_str_linger(union val *, int); static char *sock_str_timeval(union val *, int); //定義結構sock_opts, 其中包含了獲得或輸出套接口選項的所有信息 struct sock_opts { char *opt_str; //字符名稱 int opt_level; //級別 int opt_name; //名稱 char *(*opt_val_str)(union val *, int); //函數指針,用於輸出, } //定義結構數組並初始化 struct sock_opts sock_opts[ ] = { //全局變量數組才可以初始化 "SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, sock_str_flag, "SO_DEBUG", SOL_SOCKET, SO_DEBUG, sock_str_flag, #ifdef SO_REUSEPORT //編譯時用的宏定義 "SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, sock_str_flag, #else //沒有這個選項 "SO_REUSEPORT", 0, 0, NULL, //NULL表示沒有定義 #endif "SO_TYPE", SOL_SOCKET, SO_TYPE, sock_str_int, "IP_TTL", IPPROTO_IP, IP_TTL, sock_str_int, "TCP_MAXSEG", IPPROTO_TCP,TCP_MAXSEG, sock_str_int, NULL, { /*結束標志 */} 0, 0, NULL }; 源程序: int main(int argc, char **argv) { int fd, len; struct sock_opts *ptr; //結構類型 fd = Socket(AF_INET, SOCK_STREAM, 0); //獲得套接字 for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) { //從第一個選項到最後一個 printf(“%s: ”, ptr->opt_str); //輸出字符名 if (ptr->opt_val_str == NULL) //沒有定義的情況 printf("(undefined)\n"); else { len = sizeof(val); //獲得套接口選項 if (getsockopt(fd, ptr->opt_level, ptr->opt_name, val, len) == -1) { //返回值為1,函數調用失敗 err_ret("getsockopt error");} //輸出選項的缺省值 else printf("default = %s\n", (*ptr->opt_val_str)(&val, len)); } } //End of for loop exit(0); }


static char strres[128]; //靜態變量,在函數調用後保留原值 static char * sock_str_flag(union val *ptr, int len) { if (len != sizeof(int)) //長度不相符 snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len); else //轉換字符串 snprintf(strres, sizeof(strres),"%s", (ptr->i_val == 0) ? "off" : "on"); return(strres); } -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 基本套接口選項 SO_KEEPALIVE 檢測對方主機是否崩潰,避免(服務器)永遠阻塞於TCP連接的輸入。 設置該選項後,如果2小時內在此套接口的任一方向都沒有數據交換,TCP就自動給對方 發一個保持存活探測分節(keepalive probe)。這是一個對方必須響應的TCP分節.它會導 致以下三種情況: 對方接收一切正常:以期望的ACK響應。2小時後,TCP將發出另一個探測分節。 對方已崩潰且已重新啟動:以RST響應。套接口的待處理錯誤被置為ECONNRESET,套接 口本身則被關閉。 對方無任何響應:源自berkeley的TCP發送另外8個探測分節,相隔75秒一個,試圖得到 一個響應。在發出第一個探測分節11分鐘15秒後若仍無響應就放棄。套接口的待處理錯 誤被置為ETIMEOUT,套接口本身則被關閉。如ICMP錯誤是“host unreachable(主機不 可達)”,說明對方主機並沒有崩潰,但是不可達,這種情況下待處理錯誤被置為 EHOSTUNREACH。 SO_RCVBUF和SO_SNDBUF 每個套接口都有一個發送緩沖區和一個接收緩沖區。 接收緩沖區被TCP和UDP用來將接收到的數據一直保存到由應用進程來讀。 TCP:TCP通告另一端的窗口大小。 TCP套接口接收緩沖區不可能溢出,因為對方不允許發出超過所通告窗口大小的數據。 這就是TCP的流量控制,如果對方無視窗口大小而發出了超過宙口大小的數據,則接 收方TCP將丟棄它。 UDP:當接收到的數據報裝不進套接口接收緩沖區時,此數據報就被丟棄。UDP是沒有 流量控制的;快的發送者可以很容易地就淹沒慢的接收者,導致接收方的UDP丟棄數據報。 SO_LINGER 指定函數CLOSE對面相連接的協議如何操作——當由數據殘留在套接口發送緩沖區時的處理 LINGER結構 struct linger { int l_onoff; // 0=off, nonzero=on int l_linger; //linger time in seconds }; SO_RCVLOWAT 和SO_SNDLOWAT 每個套接口都有一個接收低潮限度和一個發送低潮限度。它們是函數selectt使用的, 接收低潮限度是讓select返回“可讀”而在套接口接收緩沖區中必須有的數據總量。 ——對於一個TCP或UDP套接口,此值缺省為1。發送低潮限度是讓select返回“可寫” 而在套接口發送緩沖區中必須有的可用空間。對於TCP套接口,此值常缺省為2048。 對於UDP使用低潮限度, 由於其發送緩沖區中可用空間的字節數是從不變化的,只要 UDP套接口發送緩沖區大小大於套接口的低潮限度,這樣的UDP套接口就總是可寫的。 UDP沒有發送緩沖區,只有發送緩沖區的大小。 -------------------------------------------------------------------------------- TCP 套接口選項 TCP_KEEPALIVE 指定TCP開始發送保持存活探測分節前以秒為單位的連接空閒時間。缺省值至少必須 為7200秒,即2小時。此選項僅在SO_KEPALIVEE套接口選項打開時才有效。 TCP_MAXSEG 獲取或設置TCP連接的最大分節大小(MSS)。返回值是我們的TCP發送給另一端的最大 數據量,它常常就是由另一端用SYN分節通告的MSS,除非我們的TCP選擇使用一個比 對方通告的MSS小些的值。如果此值在套接口連接之前取得,則返回值為未從另·—端 收到Mss選項的情況下所用的缺省值。小於此返回值的信可能真正用在連接上,因為譬 如說使用時間戳選項的話,它在每個分節上占用12字節的TCP選項容量。我們的TcP將 發送的每個分節的最大數據量也可在連接存活期內改變,但前提是TCP要支持路徑MTU 發現功能。如果到對方的路徑改變了,此值可上下調整。 -------------------------------------------------------------------------------- 例程序: //獲得發送緩沖區大小和MSS大小,設置發送緩沖區大小 //獲得發送緩沖區大小和MSS大小 #include "unp.h" #include /* for TCP_MAXSEG */ int main(int argc, char **argv) { int sockfd, rcvbuf, mss; socklen_t len; struct sockaddr_in servaddr; if (argc != 2) err_quit("usage: rcvbuf "); sockfd = Socket(AF_INET, SOCK_STREAM, 0); len = sizeof(rcvbuf); Getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, rcvbuf, len); len = sizeof(mss); Getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len); printf("defaults: SO_RCVBUF = %d, MSS = %d\n", rcvbuf, mss); bzero(servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(13); /* daytime server */ Inet_pton(AF_INET, argv[1], servaddr.sin_addr); Connect(sockfd, (SA *) &servaddr, sizeof(servaddr)); len = sizeof(rcvbuf); Getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &len); len = sizeof(mss); Getsockopt(sockfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &len); printf("after connect: SO_RCVBUF = %d, MSS = %d\n", rcvbuf, mss); exit(0); }

//設置發送緩沖區大小 #include "unp.h" #include /* for TCP_MAXSEG value */ in



Copyright © Linux教程網 All Rights Reserved