TCP網路知識總覽

2021-12-30 05:00:45 字數 3968 閱讀 5383

tcp網路知識總覽

tcp狀態轉換圖

tcp報文頭

三次握手

client  server

syn_sent  --------- syn j --------->

--------- ack k+1 ------->

established

syn包中可能攜帶以下資訊

mss(maximum segment size),可由tcp_maxseg獲取或設定。

window size,由so_rcvbuf決定。原為65535,後增加14bit的擴充套件視窗,因此最大值為65535 * 2^14 (1gb)。

時間戳選項。

其中,2/3由rfc1323定義。window size的擴充套件,也稱為long fat pipe(即所謂長肥管道)。

半開連線

收到客戶端的syn報文後,server處於半開half-open狀態,syn攻擊即client不執行下一步響應ack。核心中半開連線數有限,檢視linux核心backlog佇列的預設長度:

# sysctl net.ipv4.tcp_max_syn_backlog

net.ipv4.tcp_max_syn_backlog = 1024

在socket api中,listen(sockfd, backlog)的第二個引數設定即為半開連線的佇列長度,顯然超過核心限定的佇列長度沒有意義。對於半開連線攻擊(syn flood),linux中有一種名為syn cookie的保護措施。

syn初始序列號

當tcp實現傳送syn報文時,將為之選擇乙個isn(initial sequence number,初始序列號),rfc 793中指出isn是乙個32bit的計數器,每4ms加1。4.4bsd中,系統初始化時isn被設定為1(與標準建議不符),每隔0.5秒增加 64000(這個計數器每8ms加1),另外每次建立連線後,isn將增加64000。

選擇isn的目的在於防止網路中被延遲的分組在以後又被傳送,導致連線的另一端對其做出錯誤的解釋。

syn報文的超時

在linux上可見超時時間大約為3分30秒:

$ date; telnet facebook.com 80; date

sat nov 10 11:05:43 cst 2012

trying 203.98.7.65...

telnet: connect to address 203.98.7.65: connection timed out

sat nov 10 11:09:12 cst 2012

以下是對應的tcpdump抓包輸出:

從tcpdump輸出可見每次的超時時間:3、6、12、24、48、(96),超時規律即為: 3 * 2n,n取值為[0,5]。建立tcp連線的超時時間最長為:

timeout = 3 * (26 - 1) = 3 * 63 = 189

對比下《tcp/ip詳解卷1》關於tcp連線超時的描述:典型伯克利實現有3次超時,第1次超時時間在5.59-5.93秒之間變化,第2次超時時間總是24.00秒,第3次超時時間為48秒。大多數伯克利實現的tcp連線總的超時時間約為75秒。

time_wait狀態

主動關閉連線的peer會進入time_wait狀態。time_wait通常又叫做2msl,msl(maximum segment lifetime)指報文的最大生存週期。tcp建立在ip之上,而ip報文的生存週期由ttl限制,ip頭中的ttl欄位佔8bit,最大值為255, 表示乙個ip報文可被傳播的最大跳數(hop)。雖然ttl不是乙個時間值,但它確實限制了ip報文在網路中的生存時間。rfc 1122建議msl是2分鐘,伯克利版本的tcp實現通常設定為30秒,通常我們認為msl的取值為30秒到2分鐘,因此time_wait的時間為1分 鐘到4分鐘。

tcp連線處於time_wait狀態,可以防止最後發出的ack報文丟失,此時另一端的tcp實現會重發最後的fin。而處於time_wait狀態的socket pair不能再被使用。所謂socket pair其實由5個元素組成:

(local-ip, local-port, remote-ip, remote-port, protocol)

在這裡協議始終是tcp,也可認為socket pair由4元組構成。如果tcp連線處於time_wait,則4元組構成的連線只能在2msl結束後才能使用。現實中這個限制還更為嚴格一些:處於 time_wait狀態的埠預設情況下也不能使用。雖然可以通過設定so_reuseaddr來繞開這個限制,但tcp原則上仍需避免使用處於 time_wait狀態的埠。

在server開發中,如果中斷server程序,將導致time_wait連線的出現;而server必然繫結在乙個已知埠(如http的 80),因此server程式通常必然會設定so_reuseaddr。對client程式而言則影響不大,雖然client通常是主動關閉連線方,但 os總可以選擇乙個新的埠建立與server的連線(除非埠耗盡,即所有可用埠都處於time_wait)。

這裡再總結下time_wait存在的意義:

防止上一次連線的報文出現在新連線中。經過2msl的等待時間,這些報文都已失效(超過生存週期)。

如果沒有time_wait,主動關閉方將直接進入closed狀態,如果對端沒有收到最後我們最後發出的ack報文,將重發fin,此時我們已進入closed,就會響應rst而非ack,這將導致對端非正常關閉連線。

tcp的半開與半關閉狀態

所謂tcp半開狀態(half-open),即指收到syn報文,並響應syn/ack後,對端不傳送ack。

所謂tcp半關閉狀態(half-close),即指tcp連線的一方可以選擇部分關閉連線。因為tcp是全雙工連線,在一條連線上的讀/寫操作是 分開的,因此可以顯示地關閉寫信道,但還可以繼續讀取資料。應用程式用shutdown()而非close()關閉連線時,可選擇關閉讀或寫或都關閉:

shutdown(sockfd, shut_wr);

如此呼叫將給對端傳送fin,說明我沒有資料可寫了,但還可以讀資料(進入time_wait狀態)。

網路知識 TCP連線例項

例1 tcp建立連線的過程採用三次握手,已知第三次握手報文的傳送序列號是1000,確認序列號為2000,那麼第二次握手報文的傳送序列和確認序列號分別為1999,1000 解釋 假如有2個序列號,客戶端傳送a,伺服器傳送b。三次握手分別是 客戶端 傳送a 服務端 傳送b,確認a 1 客戶端 傳送a 1...

PHP網路函式總覽

checkdnsrr 給指定的主機 網域名稱 或者ip位址做dns通訊檢查 closelog 關閉系統日誌鏈結 define syslog variables 初始化所有syslog相關變數 dns check record checkdnsrr別名 dns get mx getmxrr別名 dns...

網路基本知識TCP與UDP

半雙工是在同一時刻只單向。是接收或者是傳送 全雙工是在同一時刻能雙向。可以同時接收和傳送!主要體現在網絡卡和路由,好像交換機也是!這是兩個工作在tcp ip協議傳輸層的兩個不同的協議,是用來傳輸資料用的。tcp transfer control protocol,傳輸控制協議。這是乙個全雙工的 面向...