【網絡基礎】 TCP & UDP 基礎

TCP報文格式


  • source發送TCP數據的源端口
  • dest接受TCP數據的目的端口
  • seq標識該TCP所包含的數據字節的開始序列號
  • ack_seq確認序列號,表示接受方下一次接受的數據序列號。
  • doff數據首部長度。和IP協議同樣,以4字節爲單位。通常的時候爲5
  • urg若是設置緊急數據指針,則該位爲1
  • ack若是確認號正確,那麼爲1
  • psh若是設置爲1,那麼接收方收到數據後,當即交給上一層程序
  • rst爲1的時候,表示請求從新鏈接
  • syn爲1的時候,表示請求創建鏈接
  • fin爲1的時候,表示請求關閉鏈接window窗口,告訴接收者能夠接收的大小check對TCP數據進行較核
  • urg_ptr若是urg=1,那麼指出緊急數據對於歷史數據開始的序列號的偏移值

TCP鏈接創建三次握手

  • 第一次握手:創建鏈接時,客戶端發送syn包(seq=x)到服務器,並進入SYN_SEND狀態,等待服務器確認;
  • 第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時本身也發送一個SYN包(seq=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
  • 第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
  • 完成三次握手,客戶端與服務器開始傳送數據,

TCP優缺點

優勢程序員

  • TCP提供以承認的方式顯式地建立和終止鏈接。
  • TCP保證可靠的、順序的(數據包以發送的順序接收)以及不會重複的數據傳輸。
  • TCP經過保持連續並將數據塊分紅更小的分片來處理大數據塊。無需程序員知道

缺點編程

  • TCP在傳遞數據時必須建立(並保持)一個鏈接。這個鏈接給通訊進程增長了開銷,讓它比UDP速度要慢。TCP 鏈接的資源消耗,其中包括:數據包信息、條件狀態、序列號等。
  • TCP鏈接存在安全隱患:經過故意不完成創建鏈接所須要的三次握手過程,形成鏈接一方的資源耗盡
  • 序列號的可預測性,目標主機應答鏈接請求時返回的SYN/ACK 的序列號是可預測的 TCP 會話劫持和SYN FLOOD(同步洪流)就是根據TCP的這個弱點出現的一種網絡攻擊方式

TCP 數據結構

在TCP鏈接創建的過程當中,會用到一些數據結構安全

  • 半鏈接隊列:在三次握手協議中,服務器維護一個未鏈接隊列,該隊列爲每一個客戶端的SYN包(syn=j)開設一個條目,該條目代表服務器已收到SYN 包,並向客戶發出確認,正在等待客戶的確認包。這些條目所標識的鏈接在服務器處於Syn_RECV狀態,當服務器收到客戶的確認包時,刪除該條目,服務器進入ESTABLISHED狀態。
  • Backlog參數:表示未鏈接隊列的最大容納數目。
  • SYN-ACK 重傳次數:服務器發送完SYN-ACK包,若是未收到客戶確認包,服務器進行首次重傳,等待一段時間仍未收到客戶確認包,進行第二次重傳,若是重傳次數超過系統規定的最大重傳次數,系統將該鏈接信息從半鏈接隊列中刪除。注意,每次重傳等待的時間不必定相同。
  • 半鏈接存活時間:是指半鏈接隊列的條目存活的最長時間,也即服務從收到SYN包到確認這個報文無效的最長時間,該時間值是全部重傳請求包的最長等待時間總和。有時咱們也稱半鏈接存活時間爲Timeout時間、SYN_RECV存活時間

TCP 標誌位

應該就是code bit那個字段的位的意義服務器

  • SYN(同步標誌):該標誌置上的時候,同步序列編號(Synchronize Sequence Numbers)欄有效。該標誌僅在三次握手創建TCP鏈接時有效。它提示TCP鏈接的服務端檢查序列編號,該序列編號爲TCP鏈接初始端(通常是客戶端)的初始序列編號。在這裏,能夠把TCP序列編號看做是一個範圍從0到4,294,967,295的32位計數器。經過TCP鏈接交換的數據中每個字節都通過序列編號。在TCP報頭中的序列編號欄包括了TCP分段中第一個字節的序列編號。  
  • ACK(確認標誌):該標誌置上的時候,確認編號(Acknowledgement Number)欄有效。大多數狀況下該標誌位是置位的。TCP報頭內的確認編號欄內包含的確認編號(w+1,Figure-1)爲下一個預期的序列編號,同時提示遠端系統已經成功接收全部數據。  
  • RST(復位標誌):該標誌置上的時候,用於復位相應的TCP鏈接。
  • URG(緊急標誌):該標誌置上的時候,表示緊急(The urgent pointer) 標誌有效。
  • PSH(推標誌):該標誌置位時,接收端不將該數據進行隊列處理,而是儘量快將數據轉由應用處理。在處理 telnet 或 rlogin 等交互模式的鏈接時,該標誌老是置位的。  
  • FIN(結束標誌):帶有該標誌置位的數據包用來結束一個TCP回話,但對應端口仍處於開放狀態,準備接收後續數據。

TCP鏈接過程的中間狀態

  • SYN_SENT:客戶端發送syn數據包向服務器端申請創建TCP鏈接,此時客戶端的狀態爲SYN_SENT
  • SYN_RCVD:接收方收到請求,給發起方發送一個設置了SYN與ACK標誌位的TCP數據包作爲應答,另外設置一個比客戶機發送來的ISN大1個單位的ISN值,這常被稱爲SYN_ACK數據包或SYN_ACK報文這時鏈接的狀態稱作SYN_RCVD
  • ESTABLISHED:發起方而後發送一個帶有ACK應答和增1後的ISN標誌來確認SYN_ACK至此,完成了三次握手,此時的鏈接狀態爲連結成功: ESTABLISHED

TCP鏈接終止協議(四次揮手)

因爲TCP鏈接是全雙工的,所以每一個方向都必須單獨進行關閉。這原則是當一方完成它的數據發送任務後就能發送一個FIN來終止這個方向的鏈接。收到一個 FIN只意味着這一方向上沒有數據流動,一個TCP鏈接在收到一個FIN後仍能發送數據。首先進行關閉的一方將執行主動關閉,而另外一方執行被動關閉。
TCP客戶端發送一個FIN,用來關閉客戶到服務器的數據傳送(報文段4)。
服務器收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1(報文段5)。和SYN同樣,一個FIN將佔用一個序號。
服務器關閉客戶端的鏈接,發送一個FIN給客戶端(報文段6)。
客戶段發回ACK報文確認,並將確認序號設置爲收到序號加1(報文段7)。網絡


關閉鏈接等待兩倍最大生存時間

主動關閉鏈接方發送ack響應後,爲何須要等待兩倍最大生存時間後再關閉鏈接?數據結構

由於主動方發送的ACK消息可能丟失,並致使被動方再次發送FIN報文,TIME_WAIT爲鏈接中」離羣的段」提供從網絡中消失的時間。考慮一下,若是延遲或者重傳段在鏈接關閉後到達時會發生什麼呢?一般狀況下,由於TCP僅僅丟棄該數據並響應RST消息,因此這不會形成任何問題。當RST消息到達發出延時段的主機時,由於該主機也沒有記錄鏈接的任何信息,因此它也丟棄該段。然而,若是兩個相同主機之間又創建了一個具備相同端口號的新鏈接,那麼離羣的段就可能被當作是新鏈接的,若是離羣的段中數據的任何序列號偏偏在新鏈接的當前接收窗口中,數據就會被從新接收,其結果就是破壞新鏈接併發

  • 簡單點說:就是爲了將以前的TCP鏈接的端口號給佔住,不讓新的TCP鏈接使用,避免以前TCP鏈接上發出的包(由於某些緣由比較晚纔到達目標主機)被新的TCP鏈接給收到和處理。

TCP關閉鏈接時狀態

  • CLOSED: 初始狀態。
  • LISTEN: 服務器端的某個SOCKET處於監聽狀態,能夠接受鏈接了
  • 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鏈接,但另外還告訴對方,我暫時還有點數據須要傳送給你,稍後再關閉鏈接。
  • TIME_WAIT: 表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL(2倍最大生存時間)後便可回到CLOSED可用狀態了。若是FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,能夠直接進入到TIME_WAIT狀態,而無須通過FIN_WAIT_2狀態。
  • 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

這是由於服務端的LISTEN狀態下的SOCKET當收到SYN報文的建連請求後,它能夠把ACK和SYN(ACK起應答做用,而SYN起同步做用)放在一個報文裏來發送。但關閉鏈接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你全部的數據都所有發送給對方了,因此你能夠未必會立刻會關閉SOCKET,也即你可能還須要發送一些數據給對方以後,再發送FIN報文給對方來表示你贊成如今能夠關閉鏈接了,因此它這裏的ACK報文和FIN報文多數狀況下都是分開發送的。函數


TCP Socket 編程流程圖


UDP socket 編程流程圖


UDP和TCP區別

  • UDP沒有三次握手過程。
  • UDP處理的細節比TCP少。UDP不能保證消息被傳送到(它也報告消息沒有傳送到)目的地。
  • UDP也不保證數據包的傳送順序。UDP把數據發出去後只能但願它可以抵達目的地。

UDP優缺點:

  • UDP不要求保持一個鏈接
  • UDP沒有因接收方承認收到數據包(或者當數據包沒有正確抵達而自動重傳)而帶來的開銷。
  • 設計UDP的目的是用於短應用和控制消息
  • 在一個數據包鏈接一個數據包的基礎上,UDP要求的網絡帶寬比TDP更小。

Socket概念

  • 網絡的Socket數據傳輸是一種特殊的I/O,Socket也是一種文件描述符
  • Socket也具備一個相似於打開文件的函數調用Socket(),該函數返回一個整型的Socket描述符,隨後的鏈接創建、數據傳輸等操做都是經過該Socket實現的。

Socket類型

  • 流式Socket(SOCK_STREAM):流式是一種面向鏈接的Socket,針對於面向鏈接的TCP服務應用
  • 數據報式Socket(SOCK_DGRAM):數據報式Socket是一種無鏈接的Socket,對應於無鏈接的UDP服務應用

socket調用庫函數主要有:

下面這幾個接口都會建立一個socket大數據

  • Socket(af,type,protocol):建立套接字
  • bind(sockid, local addr, addrlen):創建地址和套接字的聯繫
  • listen( Sockid ,quenlen):服務器端偵聽客戶端的請求

創建服務器/客戶端的鏈接 (面向鏈接TCP)

  • Connect(sockid, destaddr, addrlen) :客戶端請求鏈接
  • newsockid=accept(Sockid,Clientaddr, paddrlen):服務器端等待從編號爲Sockid的Socket上接收客戶鏈接請求

發送/接收數據

  • send(sockid, buff, bufflen) :面向鏈接的發送數據
  • recv( ) :面向鏈接的接收數據
  • sendto(sockid,buff,…,addrlen) 面向無鏈接發送數據
  • recvfrom( )面向無鏈接的接收數據

釋放套接字

  • close(sockid)
相關文章
相關標籤/搜索