【linux】系統編程-7-網絡編程


前言

原文html

10. 網絡編程

  • 互聯網通訊所要遵照的衆多協議,被統稱爲TCP/IP。

10.1 簡要網絡知識

  • TCP/IP是一個龐大的協議族,它是衆多網絡協議的集合,包括:ARP、IP、ICMP、UDP、TCP、DNS、DHCP、HTTP、FTP、MQTT等等
  • 分層
graph LR A[應用層] --> a[DNS HTTP FTP SMTP MQTT郵件協議] B[傳輸層] --> b[主要是TCP UDP] C[網絡層] --> c[主要爲IP ICM ARP協議] D[鏈路層] --> d[MAC層] E[物理層] --> e[主要定義物理傳輸介質]
  • 參考圖

10.2 IP協議

  • IP協議(Internet Protocol),又稱之爲網際協議,IP協議處於IP層工做,它是整個TCP/IP協議棧的核心協議

10.2.1 IP地址編址

  • 參考圖
類別 第一字節(二進制) 第一字節取值範圍 網絡號個數 主機號個數 適用範圍
A類 0XXX XXXX 0-127 125 16777214 大型網絡
B類 10XX XXXX 128-191 16368 65534 中型網絡
C類 110X XXXX 192-223 209715 254 小型網絡
D類 1110 XXXX 224-239 - - 多播
E類 1111 XXXX 240-255 - - 保留

10.2.2 特殊IP地址

10.2.1 首限廣播地址
  • 受限廣播地址用於定義整個互聯網,若是設備想使IP數據報被整個網絡所接收,就發送這個目的地址全爲1的廣播包,但這樣會給整個互聯網帶來災難性的負擔,因此在任何狀況下,路由器都會禁止轉發目的地址爲255.255.255.255的廣播數據包,所以這樣的數據包僅會出如今本地網絡中(局域網),255.255.255.255這個地址指本網段內的全部主機, 至關於「房子裏面的人都聽着」通知全部主機。
  • 其實就是對整個IP生效,即網絡號+主機號都全爲1,對整個互聯網生效
10.2.2 直接廣播地址
  • 直接廣播地址僅是主機號爲1,廣播地址表明本網絡內的全部主機。
  • 其實就是對整個IP生效,即主機號都全爲1,對同一網絡號內的全部主機生效
10.2.3 多播地址
  • 多播地址用在一對多的通訊中,屬於分類編址中的D類地址, D類地址只能用做目的地址,而不能做爲主機中的源地址。
10.2.4 迴環地址
  • 127網段的全部地址都稱爲環回地址,主要用來測試網絡協議是否工做正常的做用。好比在電腦中使用ping 命令去ping 127.1.1.1就能夠測試本地TCP/IP協議是否正常。用通俗的話表示,就是「我本身」,不能以127網段中的IP地址做爲主機地址,所以A類地址又少了一個可用網絡號。
10.2.5 本網絡本主機
  • IP地址32bit全爲0的地址(0.0.0.0)表示的是本網絡本主機,這個IP地址在IP數據報中只能用做源IP地址,這發生在當設備啓動時但又不知道本身的IP地址狀況下。
  • 在使用DHCP分配IP地址的網絡環境中,這樣的地址是很常見的,主機爲了得到一個可用的IP地址,就給DHCP服務器發送IP數據報,並用這樣的地址(0.0.0.0)做爲源地址,目的地址爲255.255.255.255(由於主機這時還不知道DHCP服務器的IP地址),而後DHCP服務器就會知道這個主機暫時沒有IP地址,那麼就會分配一個IP給這個主機。

10.3 UDP協議

  • UDP 是User Datagram Protocol的簡稱, 中文名是用戶數據報協議
  • 特色
    • 無鏈接,即通訊時不須要建立鏈接(發送數據結束時也沒有鏈接能夠釋放)因此減少了開銷和發送數據前的時延;
    • 不可靠,最大努力交付,不保證可靠交付,所以主機不須要維護複雜的鏈接狀態;
    • 面向報文,只在應用層交下來的報文前增長了首部後就向下交付IP層;
    • 無流量控制和無阻塞控制,即便網絡中存在阻塞,也不會影響發送端的發送頻率;
    • 支持一對1、一對多、多對1、多對多的交互通訊;
    • 首部開銷小,只有8個字節,它比TCP的20個字節的首部要短;
    • 速度快,UDP沒有TCP的握手、確認、窗口、重傳、擁塞控制等機制,UDP是一個無狀態的傳輸協議,因此它在傳遞數據時很是快,即便在網絡擁塞的時候UDP也不會下降發送的數據。
  • 應用環境
    • 經常使用於實時視頻的傳輸,好比直播、網絡電話等,由於即便是出現了數據丟失的狀況,致使視頻卡幀,是能夠容忍的

10.4 TCP協議

  • TCP是提供一種面向鏈接、可靠的字節流傳輸服務
  • 與UDP的區別
    • TCP面向鏈接、數據可靠。
    • UDP運載的數據是以報文的形式,各個報文在網絡中互不相干傳輸,到達目標主機的順序是不同的,因此須要在應用層進行重裝。
    • TCP採用數據流的形式傳輸,TCP協議會給每一個傳輸的字節進行編號,在傳輸的過程當中,發送方把數據的起始編號與長度放在TCP報文中,在接收方將全部數據按照編號組裝起來,而後返回一個確認,當全部數據接收完成後纔將數據遞交到應用層中。
  • TCP的特性
    • 鏈接機制:TCP是一個面向鏈接的協議
    • 確認與重傳:一個完整的TCP傳輸必須有數據的交互。發送方發送數據後必須等待接收方的結果反饋,並開啓定時器,超時未接收到數據則認爲發送失敗,進行重發操做;接收方接收到數據後必須向發送方反饋結果。
    • 緩衝機制
      • 發送方:應用程序的數據大小、類型都是不可預估的。在數據量很小時,TCP會將數據存儲在一個緩衝空間中,等到數據量足夠大的時候進行發送數據,直至確認接收方正確接收成功才刪除。
      • 接收方:因爲網絡中傳輸的數據報到達接收方的時間是不同的,因此須要存起來進行重裝再交給應用層。
    • 全雙工通訊:TCP是全雙工通訊。雙方都是主機,任意一方均可以斷開連接。
    • 流量控制
      • 流量控制是一個速度匹配服務,即發送方的發送速率與接收方應用程序的讀取速率相匹配。
      • TCP經過讓發送方維護一個稱爲接收窗口(receive window)的變量來提供流量控制。
      • 接收窗口(rwnd),接收方會將此窗口值放在 TCP 報文的首部中的窗口字段,而後傳遞給發送方,這個窗口的大小是在發送數據的時候動態調整的。
      • 若發送方收到的窗口值爲0,此時發送方仍是會進行發送只有一個字節的報文段。
    • 差錯控制:TCP協議採用校驗和的方式來檢驗數據有效性。同時,接收方也會把接收到的數據報進行整理,重裝。
    • 擁塞控制:在網絡中擁塞的狀況下調整自身的發送速度,這種形式對發送方的控制被稱爲擁塞控制(congestion control),採起的措施是限制發送方的發送速度。

10.5 端口號的概念

  • TCP鏈接是兩個不一樣主機的應用鏈接,而傳輸層與上層協議是經過端口號進行識別的。
  • 端口號的取值範圍爲:0~65535,不一樣端口號對應上層應用的不一樣線程
  • 一臺主機可能只有一個IP地址,可是能夠有多個端口號
  • 經過 IP地址+端口號 來區分主機不一樣的線程。
  • 常見的TCP協議端口號有2一、5三、80等等
端口號 協議 說明
20/21 FTP 文件傳輸協議,使得主機間能夠共享文件。
23 Telnet 終端遠程登陸,它爲用戶提供了在本地計算機上完成遠程主機工做的能力。
25 SMTP 簡單郵件傳輸協議,它幫助每臺計算機在發送或中轉信件時找到下一個目的地。
69 TFTP 普通文件傳輸協議。
80 HTTP 超文本傳輸協議,經過使用網頁瀏覽器、網絡爬蟲或者其它的工具,客戶端發起一個HTTP請求到服務器上指定端口(默認端口爲80),應答的服務器上存儲着一些資源,好比HTML文件和圖像,那麼就會返回這些數據到客戶端。
110 POP3 郵局協議版本3,本協議主要用於支持使用客戶端遠程管理在服務器上的電子郵件。

10.6 TCP報文段

  • TCP報文段由 首部 + 數據域 組成

10.7 TCP創建鏈接

  • TCP是一個面向鏈接的協議,鏈接俗稱握手。
  • 三次握手創建鏈接
    • 創建鏈接的過程是由客戶端發起,服務端等待客戶請求
    • 第一步:客戶端向服務器端發送一個SYN報文段(只有首部,且SYN被置 1),初始序號(ISN)隨機選擇,假設爲A,ACK置 0。
    • 第二步:服務器端收到SYN報文段,便知道客戶端須要請求握手,從SYN報文段中提取對應的信息,爲該TCP鏈接分配TCP緩存和變量,並向該客戶TCP發送容許鏈接的報文段(握手應答報文)。這個報文段只有首部,包含3個重要的信息:(創建客戶端-->服務端的鏈接
      1. SYN與ACK標誌位1
      2. 將TCP報文段首部的確認序號字段設置爲A+1(這個A(ISN)是從握手請求報文中獲得)。
      3. 服務器隨機選擇本身的初始序號(ISN,注意此ISN是服務器端的ISN,假設爲B),並將其放置到TCP報文段首部的序號字段中。
    • 第三步:客戶端接收到服務器端的握手應答後,會將SYN置 0,ACK置 1,確認序號置爲 B+1, 設置窗口值,能夠添加數據域的報文段發給服務器端。同時給該TCP鏈接分配緩存和變量。(創建服務端-->客戶端的鏈接
  • 參考圖:

10.8 TCP終止鏈接

  • 創建鏈接須要三次握手,而終止鏈接須要四次揮手。
  • 四次揮手終止鏈接
    • 第一步:客戶端發出FIN報文段(首部FIN被置 1),序號假設爲C,ACK被置 1,可是確認序號是無效的。
    • 第二步:當服務器端收到FIN報文段,它返回一個ACK報文段(終止鏈接應答),確認序號爲C+1。此時斷開客戶端-->服務器端的方向
    • 第三步:服務器端發出FIN報文段向客戶端請求終止鏈接,此時序號爲D,ACK被置 1,可是確認序號是無效的。
    • 第四步:當客戶端收到FIN報文段,它返回一個ACK報文段(終止鏈接應答),確認序號爲D+1。此時斷開服務器端-->客戶端的鏈接
  • 參考圖

10.9 TCP狀態

  • TCP協議的狀態以下:
    • CLOSED:初始狀態,表示TCP鏈接是「關閉着的」或「未打開的」。
    • LISTEN :表示服務器端的某個SOCKET處於監聽狀態,能夠接受客戶端的鏈接。
    • SYN_RCVD :表示服務器接收到了來自客戶端請求鏈接的SYN報文。在正常狀況下,這個狀態是服務器端的SOCKET在創建TCP鏈接時的三次握手會話過程當中的一箇中間狀態,很短暫,基本上用netstat很難看到這種狀態,除非故意寫一個監測程序,將三次TCP握手過程當中最後一個ACK報文不予發送。當TCP鏈接處於此狀態時,再收到客戶端的ACK報文,它就會進入到ESTABLISHED狀態。
    • SYN_SENT :這個狀態與SYN_RCVD狀態相呼應,當客戶端SOCKET執行connect()進行鏈接時,它首先發送SYN報文,而後隨即進入到SYN_SENT 狀態,並等待服務端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文。
    • ESTABLISHED :表示TCP鏈接已經成功創建。
    • FIN_WAIT_1 :這個狀態得好好解釋一下,其實FIN_WAIT_1FIN_WAIT_2兩種狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態其實是當SOCKETESTABLISHED狀態時,它想主動關閉鏈接,向對方發送了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是沒有超時的(不像TIME_WAIT狀態),這種狀態下若是對方不關閉(不配合完成4次揮手過程),那這個 FIN_WAIT_2 狀態將一直保持到系統重啓,愈來愈多的FIN_WAIT_2狀態會致使內核crash
    • TIME_WAIT :表示收到了對方的FIN報文,併發送出了ACK報文。 TIME_WAIT狀態下的TCP鏈接會等待2*MSL(Max Segment Lifetime,最大分段生存期,指一個TCP報文在Internet上的最長生存時間。每一個具體的TCP協議實現都必須選擇一個肯定的MSL值,RFC 1122建議是2分鐘,但BSD傳統實現採用了30秒,Linux能夠在cat/proc/sys/net/ipv4/tcp_fin_timeout看到本機的這個值),而後便可回到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報文給對方,此時TCP鏈接則進入到CLOSE_WAIT狀態。接下來呢,你須要檢查本身是否還有數據要發送給對方,若是沒有的話,那你也就能夠close()這個SOCKET併發送FIN報文給對方,即關閉本身到對方這個方向的鏈接。有數據的話則看程序的策略,繼續發送或丟棄。簡單地說,當你處於CLOSE_WAIT狀態下,須要完成的事情是等待你去關閉鏈接。
    • LAST_ACK :當被動關閉的一方在發送FIN報文後,等待對方的ACK報文的時候,就處於LAST_ACK狀態。當收到對方的ACK報文後,也就能夠進入到CLOSED可用狀態了。

參考

* 野火
相關文章
相關標籤/搜索