TCP/IP、UDP、HTTP、SOCKET詳解(非原創)

文章大綱

  1. 網絡OSI七層及各層做用
  2. TCP與UDP基本介紹
  3. TCP鏈接過程詳解
  4. SOCKET原理與鏈接詳解
 
 

1、網絡OSI七層及各層做用

 
  1. 應用層:文件傳輸,電子郵件,文件服務,虛擬終端 TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet
  2. 表示層:數據格式化,代碼轉換,數據加密 沒有協議
  3. 會話層:解除或創建與別的接點的聯繫 沒有協議
  4. 傳輸層:提供端對端的接口 TCP,UDP
  5. 網絡層:爲數據包選擇路由 IP,ICMP,RIP,OSPF,BGP,IGMP
  6. 數據鏈路層:傳輸有地址的幀以及錯誤檢測功能 SLIP,CSLIP,PPP,ARP,RARP,MTU
  7. 物理層:以二進制數據形式在物理媒體上傳輸數據 ISO2110,IEEE802,IEEE802.2

2、TCP與UDP基本介紹

TCP
  TCP:Transmission Control Protocol 傳輸控制協議TCP是一種面向鏈接(鏈接導向)的、可靠的、基於字節流的運輸層(Transport layer)通訊協議。 特色: 面向鏈接的協議,數據傳輸必需要通過三次握手創建鏈接,因此在TCP中須要鏈接時間。 傳輸數據大小限制,一旦鏈接創建,雙方能夠按統一的格式傳輸大的數據。 一個可靠的協議,確保接收方徹底正確地獲取發送方所發送的所有數據。html

UDP
  UDP: User Datagram Protocol的簡稱, 中文名是用戶數據包協議,是 OSI 參考模型中一種無鏈接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務。 特色: 每一個數據報中都給出了完整的地址信息,所以無須要創建發送方和接收方的鏈接。 UDP傳輸數據時是有大小限制的,每一個被傳輸的數據報必須限定在64KB以內。 UDP是一個不可靠的協議,發送方所發送的數據報並不必定以相同的次序到達接收方。服務器

3、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_WAIT一、FIN_WAIT二、CLOSING、TIME_WAIT
被動端可能出現的狀態:CLOSE_WAIT LAST_ACK併發

客戶端的狀態能夠用以下的流程來表示:
CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSEDsocket

服務器的狀態能夠用以下的流程來表示:
CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSEDtcp

舒適提示:
(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鏈接是全雙工的,斷開鏈接會比創建鏈接麻煩一點點。客戶端先向服務器發送FIN報文,請求斷開鏈接,其狀態變爲FIN_WAIT1。服務器收到FIN後向客戶端發生ACK,服務器狀態變爲CLOSE_WAIT。客戶端收到ACK後就進入FIN_WAIT2狀態。此時鏈接已經斷開了一半了。若是服務器還有數據要發送給客戶端,就會繼續發送。直到發完了,就發送FIN報文,此時服務器進入LAST_ACK狀態。客戶端收到服務器的FIN後,立刻發送ACK給服務器,此時客戶端進入TIME_WAIT狀態,再過了2MSL長的時間後進入CLOSED狀態。服務器收到客戶端的ACK就進入CLOSED狀態。
至此,還有一個狀態沒有說起:CLOSING狀態。CLOSING狀態表示客戶端發生了FIN,但沒有收到服務器的ACK,卻收到了服務器的FIN。這種狀況發生在服務器發送的ACK丟包的時候,由於網絡傳輸有時會有意外。url

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鏈接就創建了,客戶端和服務器能夠愉快地玩耍了。只要通訊雙方沒有一方發出鏈接釋放的請求,鏈接就將一直保持。spa

 

 
 

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計時器
  第二,防止相似與「三次握手」中提到了的「已經失效的鏈接請求報文段」出如今本鏈接中。客戶端發送完最後一個確認報文後,在這個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可用狀態了。

4、SOCKET原理與鏈接詳解

SOCKET原理

  Socket socket的英文原義是「孔」或「插座」。做爲4BDS UNIX的進程通訊機制,取後一種意思。一般也稱做「套接字」,用於描述IP地址和端口,是一個通訊鏈的句柄(引用)。 每一個插座就是一個應用程序。 細節 不一樣的通訊規則須要定義不一樣的插座。 UDP:DatagramSocket 、 DatagramPacket TCP:ServerSocket 、Socket

創建SOCKET鏈接

  創建Socket鏈接至少須要一對套接字,其中一個運行於客戶端,稱爲ClientSocket ,另外一個運行於服務器端,稱爲ServerSocket 。套接字之間的鏈接過程分爲三個步驟:服務器監聽,客戶端請求,鏈接確認。
  服務器監聽:服務器端套接字並不定位具體的客戶端套接字,而是處於等待鏈接的狀態,實時監控網絡狀態,等待客戶端的鏈接請求。
  客戶端請求:指客戶端的套接字提出鏈接請求,要鏈接的目標是服務器端的套接字。爲此,客戶端的套接字必須首先描述它要鏈接的服務器的套接字,指出服務器端套接字的地址和端口號,而後就向服務器端套接字提出鏈接請求。
  鏈接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的鏈接請求時,就響應客戶端套接字的請求,創建一個新的線程,把服務器端套接字的描述發 給客戶端,一旦客戶端確認了此描述,雙方就正式創建鏈接。而服務器端套接字繼續處於監聽狀態,繼續接收其餘客戶端套接字的鏈接請求。
鏈接實例

 
 

 

參考文章

    1. https://blog.csdn.net/qq_31337311/article/details/80781273
    2. https://www.cnblogs.com/A0926/p/5174488.html
    3. https://blog.csdn.net/hkhl_235/article/details/79721645
    4. https://www.cnblogs.com/i6010/articles/6396349.html
    5. https://blog.csdn.net/u011774517/article/details/67631439
相關文章
相關標籤/搜索