歡迎您光臨本站 註冊首頁

套介面選項

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

獲取和設置影響套介面選項的函數:
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 = %sn", (*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 = %dn", 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 = %dn", rcvbuf, mss); exit(0); }



//設置發送緩衝區大小 #include "unp.h" #include /* for TCP_MAXSEG value */ int main(int argc, char **argv) { int sockfd, mss, sendbuff; socklen_t optlen; float kk; sockfd = Socket(AF_INET, SOCK_STREAM, 0); /* Fetch and print the TCP maximum segment size. */ optlen = sizeof(mss); sendbuff =2048; Setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, sendbuff, sizeof(sendbuff)); optlen = sizeof(sendbuff); Getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, sendbuff, &optlen); printf("After send buffer size = %dn", sendbuff); exit(0); }






[火星人 ] 套介面選項已經有630次圍觀

http://coctec.com/docs/linux/show-post-57671.html