套接字除了資料通訊以外,還有其他不同的特性可以根據實際需要進行更改。
1)套接字多種可選項比如想用sol_socket、名為so_type的可選項檢視套接字型別
int tcp_sock = socket(pf_inet, sock_stream, 0); int sock_type; socklen_t optlen; int state = getsockopt(tcp_sock, sol_socket, so_type, (void*)&sock_type, &optlen):
3)so_sndbuf & so_rcvbuf看輸出緩衝大小:so_sndbuf是輸出緩衝大小相關可選項。 so_rcvbuf是輸入緩衝大小相關可選項。用這兩個可選項既可以讀取當前io緩衝大小,也可以進行更改。
int sock =
socket
(pf_inet, sock_stream,0)
;int snd_buf;
socklen_t len;
int state =
getsockopt
(sock, sol_socket, so_sndbuf,
(void*)
&snd_buf,
&len)
;printf
("output buffer size: %d \n"
, snd_buf)
;
設定輸出緩衝大小:(不會完全按照我們的要求進行)
int sock =
socket
(pf_inet, sock_stream,0)
;int snd_buf =
1024*3
;socklen_t len;
int state =
setsockopt
(sock, sol_socket, so_sndbuf,
(void*)
&snd_buf,
sizeof
(snd_buf));
printf
("output buffer size: %d \n"
, snd_buf)
;
之前是通過在客戶端控制台鍵入q,讓客戶端先通知伺服器端終止程式的。鍵入q時,呼叫close函式向伺服器端傳送fin訊息並經過四次握手過程。這樣沒什麼問題。
但是,如果我在伺服器端終止(模擬伺服器端向客戶端傳送fin訊息)程式,那伺服器端如果用同一埠號重新執行時將出現bind() error資訊,並且無法再次執行,但在這種情況下,大約再過30min即可重新執行伺服器端。
上述兩種情況的唯一區別是誰先傳輸fin訊息,結果迥然不同,為什麼呢?假設上圖中a是伺服器端,主機a向b傳送fin訊息。問題是,套接字經過四次握手後並非立即解除,而是要經過一段時間的time-wait狀態(只有先傳送fin訊息的主機才會經過time-wait狀態)。於是,伺服器端無法立即重新執行,套接字處在time-wait狀態時,相應埠是正在使用的狀態。無需考慮客戶端的time-wait狀態,因為客戶端套接字的埠號是任意指定的。與伺服器端不同,客戶端每次執行程式時都會動態分配埠號。為什麼會有time-wait狀態?上圖中假設a向b傳輸ack訊息(seq 5001、ack 7502)後立即清楚套接字。但最後這條ack訊息在傳遞途中丟失,未能傳給主機b。這時b會認為自己之前傳送的fin訊息(seq 7501、ack 5001)未能抵達主機a,繼而試圖重傳。但此時主機a已是完全終止的狀態,因此主機b永遠無法收到主機a最後傳來的ack訊息。
相反的,若主機a的套接字處在time-wait狀態,則會向主機b重傳最後的ack訊息,主機b也可以正常終止。基於這些考慮,先傳輸fin訊息的主機應該經過time-wait過程。
考慮系統發生故障從而緊急停止的情況。此時需要盡快重啟伺服器端以提供服務,但因處於time-wait狀態而必須等待幾分鐘。如圖,在主機a的四次握手中,如果最後的資料丟失,則主機b會認為a沒有能夠收到自己發出的fin訊息,因此嘗試重傳。這時,收到fin訊息的主機a將重啟time-wait計時器。因此,如果網路狀況不理想,time-wait狀態將持續。
解決方案:在套接字的可選項中更改so_reuseaddr的狀態。可將time-wait狀態下的套接字埠號重新分配給新的套接字。
so_reuseaddr預設值為0,代表無法分配time-wait狀態下的套接字埠號。
int option;
socklen_t optlen =
sizeof
(option)
;option = true;
int serv_sock =
socket
(pf_inet, sock_stream,0)
;setsockopt
(serv_sock, sol_socket, so_reuseaddr,
(void*)
&option, optlen)
;
為防止因資料過多而發生網路過載,應用於tcp層。可以看到:只有收到前一資料的ack訊息時,nagle演算法才傳送下一資料。
大檔案資料應禁用nagle演算法
int opt_val = 1; setsockopt(sock, ipproto_tcp, tcp_nodelay, (void*)&opt_val, sizeof(opt_val));
《網路程式設計》 第9章 套接字的多種可選項
ipproto ip層 ip協議相關事項 include int getsockopt int sock,int level,int optname,void optval,socklen t optlen 功能 讀取套接字可選項 引數 返回值 成功,返回0 失敗,返回 1。include int ...
網路程式設計筆記 套接字可選項
套接字具體多種特性,可通過可選項更改。1 套接字可選項和i o緩衝大小 sol locket層是套接字相關的通用可選項 ipproto ip層可選項是ip協議相關事項 ipproto tcp層可選項是tcp協議相關事項 可選項的讀取和設定通過如下兩個函式完成 include intgetsockop...
Linux網路程式設計(七) 套接字選項
1 include2 int getsockopt int sockfd,int level,int optname,void optval,socklen t optlen 3 int setsockopt int sockfd,int level,int optname,const void o...