網路程式設計 9 套接字的多種可選項

2021-08-31 13:21:52 字數 3569 閱讀 2309

套接字除了資料通訊以外,還有其他不同的特性可以根據實際需要進行更改。

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...