天天看點

TCP/IP網絡程式設計學習(8):套接字屬性設定

套接字可設定多種特性如:發送視窗和接收視窗大小、最大序列号、TTL等資訊。套接字設定是分層的,可以通過參數設定IP層,TCP層,和套接字的相關選項。每一層的可設定參數如下:

套接字屬性設定

TCP/IP網絡程式設計學習(8):套接字屬性設定

IP層

TCP/IP網絡程式設計學習(8):套接字屬性設定

TCP層:

TCP/IP網絡程式設計學習(8):套接字屬性設定

讀取套接字屬性:

int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
//sock: 用于檢視選項套接字檔案描述符。
//level: 要檢視的可選項的協定層。
//optname:要檢視的可選項名 。
//optval: 儲存結果的位址
//optlen: optval的緩沖區大小

           

設定套接字屬性:

例子:用協定層為SOL_SOCKET , 名為 SO_TYPE的可選項檢視套接字類型 ( TCP或UDP )。
socket_t optlen;
int sock_type;
state=getsockopt(tcp_sock, SOL_SOCKET, SO_TYPE, (void*)&sock_type, &optlen);
           
例子: 設定緩沖區大小,接收緩沖區(SO_REVBUF),發送緩沖區(SO_SNDBUF)。
int snd_buf=1024*3, recv_buf=1024*3;
int state;
state=setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&rcv_buf,  sizeo(recv_buf)) ;
state=setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&snd_buf,  sizeo(snd_buf)) ;
           

SO_REUSEADDR

斷開連接配接的過程:

TCP/IP網絡程式設計學習(8):套接字屬性設定
  1. 用戶端程序發出連接配接釋放封包,并且停止發送資料。釋放資料封包首部,FIN=1,其序列号為seq=u(等于前面已經傳送過來的資料的最後一個位元組的序号加1),此時,用戶端進入FIN-WAIT-1(終止等待1)狀态。 TCP規定,FIN封包段即使不攜帶資料,也要消耗一個序号。
  2. 伺服器收到連接配接釋放封包,發出确認封包,ACK=1,ack=u+1,并且帶上自己的序列号seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀态。TCP伺服器通知高層的應用程序,用戶端向伺服器的方向就釋放了,這時候處于半關閉狀态,即用戶端已經沒有資料要發送了,但是伺服器若發送資料,用戶端依然要接受。這個狀态還要持續一段時間,也就是整個CLOSE-WAIT狀态持續的時間。
  3. 用戶端收到伺服器的确認請求後,此時,用戶端就進入FIN-WAIT-2(終止等待2)狀态,等待伺服器發送連接配接釋放封包(在這之前還需要接受伺服器發送的最後的資料)。
  4. 伺服器将最後的資料發送完畢後,就向用戶端發送連接配接釋放封包,FIN=1,ack=u+1,由于在半關閉狀态,伺服器很可能又發送了一些資料,假定此時的序列号為seq=w,此時,伺服器就進入了LAST-ACK(最後确認)狀态,等待用戶端的确認。
  5. 用戶端收到伺服器的連接配接釋放封包後,必須發出确認,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此時,用戶端就進入了TIME-WAIT(時間等待)狀态。注意此時TCP連接配接還沒有釋放,必須經過2*MSL(最長封包段壽命)的時間後,當用戶端撤銷相應的TCB後,才進入CLOSED狀态。
  6. 伺服器隻要收到了用戶端發出的确認,立即進入CLOSED狀态。同樣,撤銷TCB後,就結束了這次的TCP連接配接。可以看到,伺服器結束TCP連接配接的時間要比用戶端早一些。

TIME_WAIT

主動關閉的一方采用TIME_WAIT狀态,持續時間2*MSL

如果沒有TIME_WAIT狀态。當用戶端收到伺服器FIN封包就關閉。那麼如果用戶端最後ACK封包丢失,那麼伺服器就會重新傳FIN封包,但此時用戶端已經關閉。伺服器永遠收不到最後的ACK,永遠關閉不了。

MSL(Maximum Segment Lifetime),TCP允許不同的實作可以設定不同的MSL值。

第一,保證用戶端發送的最後一個ACK封包能夠到達伺服器,因為這個ACK封包可能丢失,站在伺服器的角度看來,我已經發送了FIN+ACK封包請求斷開了,用戶端還沒有給我回應,應該是我發送的請求斷開封包它沒有收到,于是伺服器又會重新發送一次,而用戶端就能在這個2MSL時間段内收到這個重傳的封包,接着給出回應封包,并且會重新開機2MSL計時器。

第二,防止類似與“三次握手”中提到了的“已經失效的連接配接請求封包段”出現在本連接配接中。用戶端發送完最後一個确認封包後,在這個2MSL時間中,就可以使本連接配接持續的時間内所産生的所有封包段都從網絡中消失。這樣新的連接配接中不會出現舊連接配接的請求封包。

重新開機TIME_WAIT計時器
TCP/IP網絡程式設計學習(8):套接字屬性設定

在主機A的四次握手過程中 ,如果最後的資料丢失, 則主機B會認為主機A未能收到 自己發送的FIN消息,是以重傳。 這時收到FIN消息的主機A将重新開機 Time-wait定時器 。是以,如果網絡狀況不理想,Time-wait狀态将持續 。解決方案就是在套接字的可選項中更改SO_REUSEADDR的狀态 。适當調整該參數,可将TIME_WAIT狀态下的套接字端口号重新配置設定給新的套接字。SO-REUSEADDR的預設值為 0(假),這就意味着無法配置設定Time_wait狀态下的套接字端口号。

TCP NODELAY

TCP使用Nagle算法,發送延遲。Nagle算法會延遲資料包的發送,僅僅對發送隊列中最後一個資料包(未完成的資料包)起作用。其目的是解決大量的小包造成網絡負擔上升的問題,方法是囤積資料到滿足條件為止,然後發送 大資料包。下面,大包即指大小等于mss的包。發送一個小的資料包,在等待ACK的時候累積資料。當發送大檔案時應該禁止使用。設定為1為禁用,0為使用。

TCP KEEPALIVE

TCP還設有一個保活計時器,顯然,用戶端如果出現故障,伺服器不能一直等下去,白白浪費資源。伺服器每收到一次用戶端的請求後都會重新複位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到用戶端的任何資料,伺服器就會發送一個探測封包段,以後每隔75秒發送一次。若一連發送10個探測封包仍然沒反應,伺服器就認為用戶端出了故障,接着就關閉連接配接。

繼續閱讀