最開始的時候客戶端和伺服器都是處於closed狀態。主動開啟連線的為客戶端,被動開啟連線的是伺服器。1.tcp伺服器程序先建立傳輸控制塊tcb,時刻準備接受客戶程序的連線請求,此時伺服器就進入了listen(監聽)狀態;
2,tcp客戶程序也是先建立傳輸控制塊tcb,然後向伺服器發出連線請求報文,這是報文首部中的同部位syn=1,同時選擇乙個初始序列號 seq=x ,此時,tcp客戶端程序進入了 syn-sent(同步已傳送狀態)狀態。tcp規定,syn報文段(syn=1的報文段)不能攜帶資料,但需要消耗掉乙個序號。
3.tcp伺服器收到請求報文後,如果同意連線,則發出確認報文。確認報文中應該 ack=1,syn=1,確認號是ack=x+1,同時也要為自己初始化乙個序列號seq=y,此時,tcp伺服器程序進入了syn-rcvd(同步收到)狀態。這個報文也不能攜帶資料,但是同樣要消耗乙個序號。
4.tcp客戶程序收到確認後,還要向伺服器給出確認。確認報文的ack=1,ack=y+1,自己的序列號seq=x+1,此時,tcp連線建立,客戶端進入established(已建立連線)狀態。tcp規定,ack報文段可以攜帶資料,但是如果不攜帶資料則不消耗序號。
5.當伺服器收到客戶端的確認後也進入established狀態,此後雙方就可以開始通訊了。
為什麼tcp客戶端最後還要傳送一次確認呢?一句話,主要防止已經失效的連線請求報文突然又傳送到了伺服器,從而產生錯誤。
如果使用的是兩次握手建立連線,假設有這樣一種場景,客戶端傳送了第乙個請求連線並且沒有丟失,只是因為在網路結點中滯留的時間太長了,由於tcp的客戶端遲遲沒有收到確認報文,以為伺服器沒有收到,此時重新向伺服器傳送這條報文,此後客戶端和服務
器經過兩次握手完成連線,傳輸資料,然後關閉連線。此時此前滯留的那一次請求連線,網路通暢了到達了伺服器,這個報文本該是失效的,但是,兩次握手的機制將會讓客戶端和伺服器再次建立連線,這將導致不必要的錯誤和資源的浪費。如果採用的是三次握
手,就算是那一次失效的報文傳送過來了,服務端接受到了那條失效報文並且回覆了確認報文,但是客戶端不會再次發出確認。由於伺服器收不到確認,就知道客戶端並沒有請求連線。
資料傳輸完畢後,雙方都可釋放連線。最開始的時候,客戶端和伺服器都是處於established狀態,然後客戶端主動關閉,伺服器被動關閉。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連線的時間要比客戶端早一些
server端packagecom.demo.server;
import
j**a.io.bufferedoutputstream;
import
j**a.io.ioexception;
import
j**a.net.serversocket;
import
j**a.net.socket;
public
class
server
catch
(exception e)
finally
} catch
(ioexception e) }}
}}
client端packagecom.demo.client;
import
j**a.io.bufferedinputstream;
import
j**a.io.ioexception;
import
j**a.net.socket;
public
class
client
} catch
(exception e)
finally
} catch
(ioexception e) }}
}
三次握手 四次揮手
1.tcp連線的建立 1 首先是伺服器初始化的過程,從 closed 關閉 狀態開始通過順序呼叫 socket bind listen 和accept 原語建立 socket 套接字,進入 listen 監聽 狀態,等待客戶端的 tcp傳輸連線請求。2 客戶端最開始也是從 closed 狀態開始呼叫...
三次握手,四次揮手
三次握手 three times handshake three way handshake 所謂的 三次握手 即對每次傳送的 資料量是怎樣跟蹤進行協商使 資料段的傳送和接收同步,根據所接收到的資料量而確定的資料確認數及資料傳送 接收完畢後何時撤消聯絡,並建立虛連線。為了提供可靠的傳送,tcp在傳送...
三次握手 四次揮手
在tcp ip 協議中,tcp 協議提供可靠的連線服務,採用三次握手建立乙個連線,如圖1所示。1 第一次握手 建立連線時,客戶端a 傳送syn 包 syn j 到伺服器b 並進入syn send 狀態,等待伺服器b 確認。2 第二次握手 伺服器b 收到syn 包,必須確認客戶a 的syn ack j...