文章大綱
- 網絡OSI七層及各層作用
- TCP與UDP基本介紹
- TCP連接過程詳解
- SOCKET原理與連接詳解
一、網絡OSI七層及各層作用
- 應用層:文件傳輸,電子郵件,文件服務,虛擬終端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
- 表示層:數據格式化,代碼轉換,數據加密 沒有協議
- 會話層:解除或建立與別的接點的聯系 沒有協議
- 傳輸層:提供端對端的接口 TCP,UDP
- 網絡層:為數據包選擇路由 IP,ICMP,RIP,OSPF,BGP,IGMP
- 數據鏈路層:傳輸有地址的幀以及錯誤檢測功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
- 物理層:以二進制數據形式在物理媒體上傳輸數據 ISO2110,IEEE802,IEEE802.2
二、TCP與UDP基本介紹
TCP
??TCP:Transmission Control Protocol 傳輸控制協議TCP是一種面向連接(連接導向)的、可靠的、基于字節流的運輸層(Transport layer)通信協議。 特點: 面向連接的協議,數據傳輸必須要經過三次握手建立連接,所以在TCP中需要連接時間。 傳輸數據大小限制,一旦連接建立,雙方可以按統一的格式傳輸大的數據。 一個可靠的協議,確保接收方完全正確地獲取發送方所發送的全部數據。
UDP
??UDP: User Datagram Protocol的簡稱, 中文名是用戶數據包協議,是 OSI 參考模型中一種無連接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務。 特點: 每個數據報中都給出了完整的地址信息,因此無需要建立發送方和接收方的連接。 UDP傳輸數據時是有大小限制的,每個被傳輸的數據報必須限定在64KB之內。 UDP是一個不可靠的協議,發送方所發送的數據報并不一定以相同的次序到達接收方。
三、TCP連接過程詳解
基本參數介紹
LISTEN:偵聽來自遠方的TCP端口的連接請求
SYN-SENT:再發送連接請求后等待匹配的連接請求(客戶端)
SYN-RECEIVED:再收到和發送一個連接請求后等待對方對連接請求的確認(服務器)
ESTABLISHED:代表一個打開的連接
FIN-WAIT-1:等待遠程TCP連接中斷請求,或先前的連接中斷請求的確認
FIN-WAIT-2:從遠程TCP等待連接中斷請求
CLOSE-WAIT:等待從本地用戶發來的連接中斷請求
CLOSING:等待遠程TCP對連接中斷的確認
LAST-ACK:等待原來的發向遠程TCP的連接中斷請求的確認
TIME-WAIT:等待足夠的時間以確保遠程TCP接收到連接中斷請求的確認
CLOSED:沒有任何連接狀態
主動端可能出現的狀態:FIN_WAIT1、FIN_WAIT2、CLOSING、TIME_WAIT
被動端可能出現的狀態:CLOSE_WAIT LAST_ACK
客戶端的狀態可以用如下的流程來表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED
服務器的狀態可以用如下的流程來表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED
溫馨提示:
(1)主動端出現大量的FIN_WAIT1時需要注意網絡是否暢通、出現大量的FIN_WAIT2需要仔細檢查程序為何遲遲收不到對端的FIN(可能是主動方或者被動方的bug)、出現大量的TIME_WAIT需要注意系統的并發量/socket句柄資源/內存使用/端口號資源等。
(2)被動端出現大量的 CLOSE_WAIT 需要仔細檢查為何自己遲遲不愿調用close關閉連接(可能是bug,socket打開用完沒有關閉)
狀態遷移
建立連接時的狀態變遷
一開始,建立連接之前服務器和客戶端的狀態都為CLOSED。服務器創建socket后開始監聽,變為LISTEN狀態。客戶端請求建立連接,向服務器發送SYN報文,客戶端的狀態變為SYN_SENT。服務器收到客戶端的報文后向客戶端發送ACK和SYN報文,此時服務器的狀態變為SYN_RCVD。然后,客戶端收到ACK、SYN,就向服務器發送ACK,客戶端狀態變為ESTABLISHED,服務器收到客戶端的ACK后也變為ESTABLISHED。此時,3次握手完成,連接建立!
斷開連接時的狀態變遷
由于tcp連接是全雙工的,斷開連接會比建立連接麻煩一點點??蛻舳讼认蚍掌靼l送FIN報文,請求斷開連接,其狀態變為FIN_WAIT1。服務器收到FIN后向客戶端發生ACK,服務器狀態變為CLOSE_WAIT??蛻舳耸盏紸CK后就進入FIN_WAIT2狀態。此時連接已經斷開了一半了。如果服務器還有數據要發送給客戶端,就會繼續發送。直到發完了,就發送FIN報文,此時服務器進入LAST_ACK狀態??蛻舳耸盏椒掌鞯腇IN后,馬上發送ACK給服務器,此時客戶端進入TIME_WAIT狀態,再過了2MSL長的時間后進入CLOSED狀態。服務器收到客戶端的ACK就進入CLOSED狀態。
至此,還有一個狀態沒有提及:CLOSING狀態。CLOSING狀態表示客戶端發生了FIN,但沒有收到服務器的ACK,卻收到了服務器的FIN。這種情況發生在服務器發送的ACK丟包的時候,因為網絡傳輸有時會有意外。
tcp連接建立(tcp三握手)
??TCP連接的建立采用客戶-服務器模式:主動發起連接建立的應用進程叫做客戶,被動等待連接建立的應用進程叫做服務器。
??連接建立階段:
??第一次握手:客戶端的應用進程主動打開,并向服務端發出請求報文段。其首部中:SYN=1,seq=x。
??第二次握手:服務器應用進程被動打開。若同意客戶端的請求,則發回確認報文,其首部中:SYN=1,ACK=1,ack=x+1,seq=y。
??第三次握手:客戶端收到確認報文之后,通知上層應用進程連接已建立,并向服務器發出確認報文,其首部:ACK=1,ack=y+1。當服務器收到客戶端的確認報文之后,也通知其上層應用進程連接已建立。
在這個過程中,通信雙方的狀態如下圖,其中CLOSED:關閉狀態、LISTEN:收聽狀態、SYN-SENT:同步已發送、SYN-RCVD:同步收到、ESTAB-LISHED:連接已建立
至此,TCP連接就建立了,客戶端和服務器可以愉快地玩耍了。只要通信雙方沒有一方發出連接釋放的請求,連接就將一直保持。
tcp連接終止協議*(tcp四揮手)
??由于TCP連接是全雙工的,因此每個方向都必須單獨進行關閉。這原則是當一方完成它的數據發送任務后就能發送一個FIN來終止這個方向的連接。收到一個 FIN只意味著這一方向上沒有數據流動,一個TCP連接在收到一個FIN后仍能發送數據。首先進行關閉的一方將執行主動關閉,而另一方執行被動關閉。
(1) TCP客戶端發送一個FIN,用來關閉客戶到服務器的數據傳送。
(2) 服務器收到這個FIN,它發回一個ACK,確認序號為收到的序號加1。和SYN一樣,一個FIN將占用一個序號。
(3) 服務器關閉客戶端的連接,發送一個FIN給客戶端。
(4) 客戶端發回ACK報文確認,并將確認序號設置為收到序號加1。
為什么客戶端最后還要等待2MSL?
??MSL(Maximum Segment Lifetime),TCP允許不同的實現可以設置不同的MSL值。
??第一,保證客戶端發送的最后一個ACK報文能夠到達服務器,因為這個ACK報文可能丟失,站在服務器的角度看來,我已經發送了FIN+ACK報文請求斷開了,客戶端還沒有給我回應,應該是我發送的請求斷開報文它沒有收到,于是服務器又會重新發送一次,而客戶端就能在這個2MSL時間段內收到這個重傳的報文,接著給出回應報文,并且會重啟2MSL計時器。
??第二,防止類似與“三次握手”中提到了的“已經失效的連接請求報文段”出現在本連接中??蛻舳税l送完最后一個確認報文后,在這個2MSL時間中,就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失。這樣新的連接中不會出現舊連接的請求報文。
??為什么建立連接是三次握手,關閉連接確是四次揮手呢?
??建立連接的時候,服務器在LISTEN狀態下,收到建立連接請求的SYN報文后,把ACK和SYN放在一個報文里發送給客戶端。而關閉連接時,服務器收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,而自己也未必全部數據都發送給對方了,所以己方可以立即關閉,也可以發送一些數據給對方后,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送,從而導致多了一次。
參數詳解
CLOSED
??這個沒什么好說的了,表示初始狀態。
LISTEN
??這個也是非常容易理解的一個狀態,表示服務器端的某個SOCKET處于監聽狀態,可以接受連接了。
SYN_RCVD
??這個狀態表示接受到了SYN報文,在正常情況下,這個狀態是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一個中間狀態,很短暫,基本上用netstat你是很難看到這種狀態的,除非你特意寫了一個客戶端測試程序,故意將三次TCP握手過程中最后一個ACK報文不予發送。因此這種狀態時,當收到客戶端的ACK報文后,它會進入到ESTABLISHED狀態。
SYN_SENT
??這個狀態與SYN_RCVD遙想呼應,當客戶端SOCKET執行CONNECT連接時,它首先發送SYN報文,因此也隨即它會進入到了SYN_SENT狀態,并等待服務端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文。
ESTABLISHED
??這個容易理解了,表示連接已經建立了。
FIN_WAIT_1
??這個狀態要好好解釋一下,其實FIN_WAIT_1和FIN_WAIT_2狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET即進入到FIN_WAIT_1狀態。而當對方回應ACK報文后,則進入到FIN_WAIT_2狀態,當然在實際的正常情況下,無論對方何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1狀態一般是比較難見到的,而FIN_WAIT_2狀態還有時常常可以用netstat看到。
FIN_WAIT_2
??上面已經詳細解釋了這種狀態,實際上FIN_WAIT_2狀態下的SOCKET,表示半連接,也即有一方要求close連接,但另外還告訴對方,我暫時還有點數據需要傳送給你,稍后再關閉連接這就是著名的半關閉的狀態了,這是在關閉連接時,客戶端和服務器兩次握手之后的狀態。在這個狀態下,應用程序還有接受數據的能力,但是已經無法發送數據,但是也有一種可能是,客戶端一直處于FIN_WAIT_2狀態,而服務器則一直處于WAIT_CLOSE狀態,而直到應用層來決定關閉這個狀態
TIME_WAIT
??表示收到了對方的FIN報文,并發送出了ACK報文,就等2MSL后即可回到CLOSED可用狀態了。如果FIN_WAIT_1狀態下,收到了對方同時帶FIN標志和ACK標志的報文時,可以直接進入到TIME_WAIT狀態,而無須經過FIN_WAIT_2狀態。
CLOSING
??這里先說一下另一種狀態(同時打開)
??RST是另一種關閉連接的方式,應用程序應該可以判斷RST包的真實性,即是否為異常中止。而同時打開和同時關閉則是兩種特殊的TCP狀態,發生的概率很小。
下面說closing狀態 ,這種狀態比較特殊,實際情況中應該是很少見,屬于一種比較罕見的例外狀態。正常情況下,當你發送FIN報文后,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING狀態表示你發送FIN報文后,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什么情況下會出現此種情況呢?其實細想一下,也不難得出結論:那就是如果雙方幾乎在同時close一個SOCKET的話,那么就出現了雙方同時發送FIN報文的情況,也就會出現CLOSING狀態,表示雙方都正在關閉SOCKET連接。
CLOSE_WAIT
??這種狀態的含義其實是表示在等待關閉。怎么理解呢?當對方close一個SOCKET后發送FIN報文給自己,你系統毫無疑問地會回應一個ACK報文給對方,此時則進入到CLOSE_WAIT狀態。接下來呢,實際上你真正需要考慮的事情是查看你是否還有數據發送給對方,如果沒有的話,那么你也就可以close這個SOCKET,發送FIN報文給對方,也即關閉連接。所以你在CLOSE_WAIT狀態下,需要完成的事情是等待你去關閉連接。
LAST_ACK
??這個狀態還是比較容易好理解的,它是被動關閉一方在發送FIN報文后,最后等待對方的ACK報文。當收到ACK報文后,也即可以進入到CLOSED可用狀態了。
四、SOCKET原理與連接詳解
SOCKET原理
??Socket socket的英文原義是“孔”或“插座”。作為4BDS UNIX的進程通信機制,取后一種意思。通常也稱作“套接字”,用于描述IP地址和端口,是一個通信鏈的句柄(引用)。 每個插座就是一個應用程序。 細節 不同的通信規則需要定義不同的插座。 UDP:DatagramSocket 、 DatagramPacket TCP:ServerSocket 、Socket
建立SOCKET連接
??建立Socket連接至少需要一對套接字,其中一個運行于客戶端,稱為ClientSocket ,另一個運行于服務器端,稱為ServerSocket 。套接字之間的連接過程分為三個步驟:服務器監聽,客戶端請求,連接確認。
??服務器監聽:服務器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態,實時監控網絡狀態,等待客戶端的連接請求。
??客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求。
??連接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發 給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續處于監聽狀態,繼續接收其他客戶端套接字的連接請求。
連接實例
參考文章