TCP/IP詳解 (轉)

TCP/IP詳解學習筆記(1)-基本概念html

爲何會有TCP/IP協議linux

在世界上各地,各類各樣的電腦運行着各自不一樣的操做系統爲你們服務,這些電腦在表達同一種信息的時候所使用的方法是千差萬別。就好像聖經中上帝打亂了各地人的口音,讓他們沒法合做同樣。計算機使用者意識到,計算機只是單兵做戰並不會發揮太大的做用。只有把它們聯合起來,電腦纔會發揮出它最大的潛力。因而人們就千方百計的用電線把電腦鏈接到了一塊兒。git

可是簡單的連到一塊兒是遠遠不夠的,就好像語言不一樣的兩我的互相見了面,徹底不能交流信息。於是他們須要定義一些共通的東西來進行交流,TCP/IP就是爲此而生。TCP/IP不是一個協議,而是一個協議族的統稱。裏面包括了IP協議,IMCP協議,TCP協議,以及咱們更加熟悉的http、ftp、pop3協議等等。電腦有了這些,就好像學會了外語同樣,就能夠和其餘的計算機終端作自由的交流了。算法

TCP/IP協議分層

提到協議分層,咱們很容易聯想到ISO-OSI的七層協議經典架構,可是TCP/IP協議族的結構則稍有不一樣。如圖所示數據庫

TCP/IP協議族按照層次由上到下,層層包裝。最上面的就是應用層了,這裏面有http,ftp,等等咱們熟悉的協議。而第二層則是傳輸層,著名的TCP和UDP協議就在這個層次(不要告訴我你沒用過udp玩星際)。第三層是網絡層,IP協議就在這裏,它負責對數據加上IP地址和其餘的數據(後面會講到)以肯定傳輸的目標。第四層是叫數據鏈路層,這個層次爲待傳送的數據加入一個以太網協議頭,並進行CRC編碼,爲最後的數據傳輸作準備。再往下則是硬件層次了,負責網絡的傳輸,這個層次的定義包括網線的制式,網卡的定義等等(這些咱們就不用關心了,咱們也不作網卡),因此有些書並不把這個層次放在tcp/ip協議族裏面,由於它幾乎和tcp/ip協議的編寫者沒有任何的關係。發送協議的主機從上自下將數據按照協議封裝,而接收數據的主機則按照協議從獲得的數據包解開,最後拿到須要的數據。這種結構很是有棧的味道,因此某些文章也把tcp/ip協議族稱爲tcp/ip協議棧。編程

一些基本的常識

在學習協議以前,咱們應該具有一些基本知識。windows

  • 互聯網地址(ip地址)

    網絡上每個節點都必須有一個獨立的Internet地址(也叫作IP地址)。如今,一般使用的IP地址是一個32bit的數字,也就是咱們常說的IPv4標準,這32bit的數字分紅四組,也就是常見的255.255.255.255的樣式。IPv4標準上,地址被分爲五類,咱們經常使用的是B類地址。具體的分類請參考其餘文檔。須要注意的是IP地址是網絡號+主機號的組合,這很是重要。緩存

  • 域名系統

    域名系統是一個分佈的數據庫,它提供將主機名(就是網址啦)轉換成IP地址的服務。安全

  • RFC

    RFC是什麼?RFC就是tcp/ip協議的標準文檔,在這裏咱們能夠看到RFC那長長的定義列表,如今它一共有4000多個協議的定義,固然,咱們所要學習的,也就是那麼十幾個協議而已。服務器

  • 端口號(port)

    注意,這個號碼是用在TCP,UDP上的一個邏輯號碼,並非一個硬件端口,咱們平時說把某某端口封掉了,也只是在IP層次把帶有這個號碼的IP包給過濾掉了而已。

  • 應用編程接口

    如今經常使用的編程接口有socket和TLI。而前面的有時候也叫作「Berkeley socket」,可見Berkeley對於網絡的發展有多大的貢獻。

  • TCP/IP詳解學習筆記(2)-數據鏈路層


    數據鏈路層有三個目的:

    • IP模塊發送和 接收IP數據報。
    • ARP模塊發送ARP請求和接收ARP應答。
    • RARP發送RARP 求和接收RARP應答

    ip你們都據說過。至於ARPRARPARP叫作地址解析協議,是用IP地址換MAC地址的一種協議,而RARP則叫作逆地址解析協議,在tcp/ip協議的後面章節會介紹它們(在局域網裏面用ARP協議能夠很容易的搞癱瘓網絡哦)

    數據鏈路層的協議仍是不少的,有咱們最經常使用的以太網(就是平時咱們用的網卡)協議,也有不太常見的令牌環,還有FDDI,固然,還有國內如今至關普及的PPP協議(就是adsl寬帶),以及一個loopback協議。

    聯繫linux裏面的ifconfig -a命令,這個命令一般會獲得以下的結果

    eth0 Link encap:Ethernet HWaddr 00:01:4A:03:5B:ED
    inet addr:192.168.11.2 Bcast:192.168.11.255 Mask:255.255.255.0
    inet6 addr: fe80::201:4aff:fe03:5bed/64 Scope:Link
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:2819 errors:0 dropped:0 overruns:0 frame:0
    TX packets:76 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:241609 (235.9 KiB) TX bytes:9596 (9.3 KiB)

    lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    inet6 addr: ::1/128 Scope:Host
    UP LOOPBACK RUNNING MTU:16436 Metric:1
    RX packets:2713 errors:0 dropped:0 overruns:0 frame:0
    TX packets:2713 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:0
    RX bytes:3516032 (3.3 MiB) TX bytes:3516032 (3.3 MiB)

     

    其中,eth0就是以太網接口,而lo則是loopback接口。這也說明這個主機在網絡鏈路層上至少支持loopback協議和以太網協議。

    以太網(Ether-net)的定是指數字設備公司( Digital Equipment Corp.)、英特爾公司(Intel Corp.)和Xerox公司在1982年聯合公佈的一個標準,這個標準裏面使用了一種稱做CSMA/CD的接入方法。而IEEE802提供的標準集802.3(還有一部分定義到了802.2)也提供了一個CSMA/CD的標準。這兩個標準稍有不一樣,TCP/IP協議對這種狀況的處理方式以下:

    • 以太網的IP數據報封裝在RFC894中定義,而IEEE802網絡的IP數據報封裝在RFC1042中定義。
    • 一臺主機必定要能發送和接收RFC894定義的數據報。
    • 一臺主機能夠接收RFC894RFC1042的封裝格式的混合數據報。
    • 一臺主機也許可以發送RFC1042數據報。。若是主機能同時發送兩種類型的分組數 據,那麼發送的分組必須是能夠設置的,並且默認條件下必須是RFC 894分組。

    可見,RFC1042TCP/IP裏面處於一個配角的地位。這兩種不一樣的數據報格式請參考教材。

    ppp(點對點協議)是從SLIP的替代品。他們都提供了一種低速接入的解決方案。而每一種數據鏈路層協議,都有一個MTU(最大傳輸單元)定義,在這個定義下面,若是IP數據報過大,則要進行分片(fragmentation),使得每片都小於MTU,注意PPPMTU並非一個物理定義,而是指一個邏輯定義(我的認爲就是用程序控制)。能夠用netstat來打印出MTU的結果,好比鍵入netstat -in

    Kernel Interface table
    Iface       MTU Met    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
    eth0       1500   0     1774      0      0      0      587      0      0      0 BMRU
    lo        16436   0     2667      0      0      0     2667      0      0      0 LRU

    就能夠觀察到eth0MTU1500。而lo(環回接口)的MTU則是16436

    最後說說那個環回接口(loopback)。平時咱們用127.0.0.1來嘗試本身的機器服務器好使很差使。走的就是這個loopback接口。對於環回接口,有以下三點值得注意:

    • 傳給環回地址(通常是127.0.0.1)的任何數據均做爲I P輸入。
    • 傳給廣播地址或多播地址的數據報復制一份傳給環回接口,而後送到以太網上。這是 由於廣播傳送和多播傳送的定義包含主機自己。
    • 任何傳給該主機IP地址的數據均送到環回接口。

    這一章仍是很簡單的,通常做爲了解知識也就足夠了,不必摳的那麼詳細。

    TCP/IP詳解學習筆記(3)-IP協議,ARP協議,RARP協議

    把這三個協議放到一塊兒學習是由於這三個協議處於同一層,ARP協議用來找到目標主機的Ethernet網卡Mac地址,IP則承載要發送的消息。數據鏈路層能夠從ARP獲得數據的傳送信息,而從IP獲得要傳輸的數據信息。

    1.IP協議

    IP協議是TCP/IP協議的核心,全部的TCPUDPIMCPIGCP的數據都以IP數據格式傳輸。要注意的是,IP不是可靠的協議,這是說,IP協議沒有提供一種數據未傳達之後的處理機制--這被認爲是上層協議--TCPUDP要作的事情。因此這也就出現了TCP是一個可靠的協議,而UDP就沒有那麼可靠的區別。這是後話,暫且不提

    1.1.IP協議頭

    如圖所示


    挨個解釋它是教科書的活計,我感興趣的只是那八位的TTL字段,還記得這個字段是作什麼的麼?這個字段規定該數據包在穿過多少個路由以後纔會被拋棄(這裏就體現出來IP協議包的不可靠性,它不保證數據被送達),某個ip數據包每穿過一個路由器,該數據包的TTL數值就會減小1,當該數據包的TTL成爲零,它就會被自動拋棄。這個字段的最大值也就是255,也就是說一個協議包也就在路由器裏面穿行255次就會被拋棄了,根據系統的不一樣,這個數字也不同,通常是32或者是64Tracerouter這個工具就是用這個原理工做的,tranceroute-m選項要求最大值是255,也就是由於這個TTLIP協議裏面只有8bit

    如今的ip版本號是4,因此也稱做IPv4。如今還有IPv6,並且運用也愈來愈普遍了。

    1.2.IP路由選擇

    當一個IP數據包準備好了的時候,IP數據包(或者說是路由器)是如何將數據包送到目的地的呢?它是怎麼選擇一個合適的路徑來"送貨"的呢?

    最特殊的狀況是目的主機和主機直連,那麼主機根本不用尋找路由,直接把數據傳遞過去就能夠了。至因而怎麼直接傳遞的,這就要靠ARP協議了,後面會講到。

    稍微通常一點的狀況是,主機經過若干個路由器(router)和目的主機鏈接。那麼路由器就要經過ip包的信息來爲ip包尋找到一個合適的目標來進行傳遞,好比合適的主機,或者合適的路由。路由器或者主機將會用以下的方式來處理某一個IP數據包

    1. 若是IP數據包的TTL(生命週期)以到,則該IP數據包就被拋棄。
    2. 搜索路由表,優先搜索匹配主機,若是能找到和IP地址徹底一致的目標主機,則將該包發向目標主機
    3. 搜索路由表,若是匹配主機失敗,則匹配同子網的路由器,這須要子網掩碼(1.3.)」的協助。若是找到路由器,則將該包發向路由器。
    4. 搜索路由表,若是匹配同子網路由器失敗,則匹配同網號(第一章有講解)路由器,若是找到路由器,則將該包發向路由器。
    5. 搜索陸游表,若是以上都失敗了,就搜索默認路由,若是默認路由存在,則發包
    6. 若是都失敗了,就丟掉這個包。

    這再一次證實了,ip包是不可靠的。由於它不保證送達。

    1.3.子網尋址

    IP地址的定義是網絡號+主機號。可是如今全部的主機都要求子網編址,也就是說,把主機號在細分紅子網號+主機號。最終一個IP地址就成爲 網絡號碼+子網號+主機號。例如一個B類地址:210.30.109.134。通常狀況下,這個IP地址的紅色部分就是網絡號,而藍色部分就是子網號,綠色部分就是主機號。至於有多少位表明子網號這個問題上,這沒有一個硬性的規定,取而代之的則是子網掩碼,校園網相信大多數人都用過,在校園網的設定裏面有一個255.255.255.0的東西,這就是子網掩碼。子網掩碼是由32bit的二進制數字序列,形式爲是一連串的1和一連串的0,例如:255.255.255.0(二進制就是11111111.11111111.11111111.00000000)對於剛纔的那個B類地址,由於210.30是網絡號,那麼後面的109.134就是子網號和主機號的組合,又由於子網掩碼只有後八bit0,因此主機號就是IP地址的後八個bit,就是134,而剩下的就是子網號碼--109

    2. ARP協議

    還記得數據鏈路層的以太網的協議中,每個數據包都有一個MAC地址頭麼?咱們知道每一塊以太網卡都有一個MAC地址,這個地址是惟一的,那麼IP包是如何知道這個MAC地址的?這就是ARP協議的工做。

    ARP(地址解析)協議是一種解析協議,原本主機是徹底不知道這個IP對應的是哪一個主機的哪一個接口,當主機要發送一個IP包的時候,會首先查一下本身的ARP高速緩存(就是一個IP-MAC地址對應表緩存),若是查詢的IPMAC值對不存在,那麼主機就向網絡發送一個ARP協議廣播包,這個廣播包裏面就有待查詢的IP地址,而直接收到這份廣播的包的全部主機都會查詢本身的IP地址,若是收到廣播包的某一個主機發現本身符合條件,那麼就準備好一個包含本身的MAC地址的ARP包傳送給發送ARP廣播的主機,而廣播主機拿到ARP包後會更新本身的ARP緩存(就是存放IP-MAC對應表的地方)。發送廣播的主機就會用新的ARP緩存數據準備好數據鏈路層的的數據包發送工做。

    一個典型的arp緩存信息以下,在任意一個系統裏面用arp -a」命令:

    Interface: 192.168.11.3 --- 0x2
      Internet Address      Physical Address      Type
      192.168.11.1          00-0d-0b-43-a0-2f     dynamic
      192.168.11.2          00-01-4a-03-5b-ea     dynamic

     

     

    都會獲得這樣的結果。

    這樣的高速緩存是有時限的,通常是20分鐘(伯克利系統的衍生系統)。

    TCP/IP詳解學習筆記(4)-ICMP協議,ping和Traceroute

    1.IMCP協議介紹

    前面講到了,IP協議並非一個可靠的協議,它不保證數據被送達,那麼,天然的,保證數據送達的工做應該由其餘的模塊來完成。其中一個重要的模塊就是ICMP(網絡控制報文)協議。

    當傳送IP數據包發生錯誤--好比主機不可達,路由不可達等等,ICMP協議將會把錯誤信息封包,而後傳送回給主機。給主機一個處理錯誤的機會,這 也就是爲何說創建在IP層以上的協議是可能作到安全的緣由。ICMP數據包由8bit的錯誤類型和8bit的代碼和16bit的校驗和組成。而前 16bit就組成了ICMP所要傳遞的信息。書上的圖63清楚的給出了錯誤類型和代碼的組合表明的意思。

    儘管在大多數狀況下,錯誤的包傳送應該給出ICMP報文,可是在特殊狀況下,是不產生ICMP錯誤報文的。以下

    1. ICMP差錯報文不會產生ICMP差錯報文(出IMCP查詢報文)(防止IMCP的無限產生和傳送)
    2. 目的地址是廣播地址或多播地址的IP數據報。
    3. 做爲鏈路層廣播的數據報。
    4. 不是IP分片的第一片。
    5. 源地址不是單個主機的數據報。這就是說,源地址不能爲零地址、環回地址、廣播地 址或多播地址。

    雖然裏面的一些規定如今還不是很明白,可是全部的這一切規定,都是爲了防止產生ICMP報文的無限傳播而定義的。

    ICMP協議大體分爲兩類,一種是查詢報文,一種是差錯報文。其中查詢報文有如下幾種用途:

    1. ping查詢(不要告訴我你不知道ping程序)
    2. 子網掩碼查詢(用於無盤工做站在初始化自身的時候初始化子網掩碼)
    3. 時間戳查詢(能夠用來同步時間)

    而差錯報文則產生在數據傳送發生錯誤的時候。就不贅述了。

    2.ICMP的應用--ping

    ping能夠說是ICMP的最著名的應用,當咱們某一個網站上不去的時候。一般會ping一下這個網站。ping會回顯出一些有用的信息。通常的信息以下:

    Reply from 10.4.24.1: bytes=32 time<1ms TTL=255
    Reply from 10.4.24.1: bytes=32 time<1ms TTL=255
    Reply from 10.4.24.1: bytes=32 time<1ms TTL=255
    Reply from 10.4.24.1: bytes=32 time<1ms TTL=255

    Ping statistics for 10.4.24.1:
        Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
    Approximate round trip times in milli-seconds:
        Minimum = 0ms, Maximum = 0ms, Average = 0ms

    ping這個單詞源自聲納定位,而這個程序的做用也確實如此,它利用ICMP協議包來偵測另外一個主機是否可達。原理是用類型碼爲0ICMP發請 求,受到請求的主機則用類型碼爲8ICMP迴應。ping程序來計算間隔時間,並計算有多少個包被送達。用戶就能夠判斷網絡大體的狀況。咱們能夠看到, ping給出來了傳送的時間和TTL的數據。我給的例子不太好,由於走的路由少,有興趣地能夠ping一下國外的網站好比sf.net,就能夠觀察到一些 丟包的現象,而程序運行的時間也會更加的長。
    ping
    還給咱們一個看主機到目的主機的路由的機會。這是由於,ICMPping請求數據報在每通過一個路由器的時候,路由器都會把本身的ip放到該數 據報中。而目的主機則會把這個ip列表複製到迴應icmp數據包中發回給主機。可是,不管如何,ip頭所能紀錄的路由列表是很是的有限。若是要觀察路由, 咱們仍是須要使用更好的工具,就是要講到的Traceroute(windows下面的名字叫作tracert)

    3.ICMP的應用--Traceroute

    Traceroute是用來偵測主機到目的主機之間所經路由狀況的重要工具,也是最便利的工具。前面說到,儘管ping工具也能夠進行偵測,可是,由於ip頭的限制,ping不能徹底的記錄下所通過的路由器。因此Traceroute正好就填補了這個缺憾。

    Traceroute的原理是很是很是的有意思,它受到目的主機的IP後,首先給目的主機發送一個TTL=1(還記得TTL是什麼嗎?)的UDP(後面就 知道UDP是什麼了)數據包,而通過的第一個路由器收到這個數據包之後,就自動把TTL1,而TTL變爲0之後,路由器就把這個包給拋棄了,並同時產生 一個主機不可達的ICMP數據報給主機。主機收到這個數據報之後再發一個TTL=2UDP數據報給目的主機,而後刺激第二個路由器給主機發ICMP數據 報。如此往復直到到達目的主機。這樣,traceroute就拿到了全部的路由器ip。從而避開了ip頭只能記錄有限路由IP的問題。

    有人要問,我怎麼知道UDP到沒到達目的主機呢?這就涉及一個技巧的問題,TCPUDP協議有一個端口號定義,而普通的網絡程序只監控少數的幾個號碼較 小的端口,好比說80,好比說23,等等。而traceroute發送的是端口號>30000(真變態)UDP報,因此到達目的主機的時候,目的 主機只能發送一個端口不可達的ICMP數據報給主機。主機接到這個報告之後就知道,主機到了,因此,說Traceroute是一個騙子一點也不爲過:)

    Traceroute程序裏面提供了一些頗有用的選項,甚至包含了IP選路的選項,請察看man文檔來了解這些,這裏就不贅述了。

    TCP/IP詳解學習筆記(5)-IP選路,動態選路,和一些細節

    1.靜態IP選路

    1.1.一個簡單的路由表

    選路是IP層最重要的一個功能之一。前面的部分已經簡單的講過路由器是經過何種規則來根據IP數據包的IP地址來選擇路由。這裏就不重複了。首先來看看一個簡單的系統路由表。

    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    192.168.11.0    *               255.255.255.0   U     0      0        0 eth0
    169.254.0.0     *               255.255.0.0     U     0      0        0 eth0
    default         192.168.11.1    0.0.0.0         UG    0      0        0 eth0

    對於一個給定的路由器,能夠打印出五種不一樣的flag

    1. U代表該路由可用。
    2. G代表該路由是到一個網關。若是沒有這個標誌,說明和Destination是直連的,而相應的Gateway應該直接給出Destination的地址。
    3. H代表該路由是到一個主機,若是沒有該標誌,說明Destination是一個網絡,換句話說Destination就應該寫成一個網絡號和子網號的組合,而不包括主機號(主機號碼處爲0),例如 192.168.11.0
    4. D代表該路由是爲重定向報文建立的
    5. M該路由已經被重定向報文修改

    U沒啥可說的,G說明這是一個網關,若是你要發數據給DestinationIP頭應該寫DestinationIP地址,而數據鏈路層的MAC地址就應該是GateWayMac地址了;反之,若是沒有G標誌,那麼數據鏈路層和IP層的地址應該是對應的。H說明了Destination的性質,若是是H的,則說明該地址是一個完整的地址,既有網絡號又有主機號,那麼再匹配的時候就既要匹配網絡號,又要匹配主機號;反之,Destination就表明一個網絡,在匹配的時候只要匹配一下網絡號就能夠了。

    這樣,IP選路的方式就能夠更加具體化了。以下

    1. 首先用IP地址來匹配那些帶H標誌的DestinationIP地址。
    2. 若是1失敗就匹配那些網絡地址。
    3. 若是2失敗就發送到Default網關

    順便提一下那個GenMask(還記得子網掩碼麼),它指定了目的地址的子網號,例如第一條的子網就是11

    1.2.其餘有關路由表的知識

    通常,咱們在配置好一個網絡接口的時候,一個路由就被直接建立好了。固然咱們也能夠手動添加路由。用route add命令就能夠了。

    而當一個IP包在某一個路由器的時候發現沒有路由可走,那麼該路由器就會給源主機發送主機不可達或者網絡不可達ICMP包來報錯。

    注意,通常的操做系統默認是沒有路由功能的,這須要本身配置。這些歷史緣由就不細說了,

    1.3.ICMPIP重定向報文和路由發現報文

    IP包在某一個地方轉向的時候,都回給發送IP報的源主機一個ICMP重定向報文,而源主機就能夠利用這個信息來更新本身的路由表,這樣,隨着網絡通訊的逐漸增多,路由表也就愈來愈完備,數據轉發的速度也會愈來愈快。咱們須要注意的是:

    1. 重定向報文只能由路由器發出。
    2. 重定向報文爲主機所用,而不是爲路由器所用。

    在主機引導的時候,通常會發送在網內廣播一個路由請求的ICMP報文,而多個路由器則會迴應一個路由通告報文。並且,路由其自己不按期的在網絡內發佈路由通告報文,這樣,根據這些報文,每個主機都會有機會創建本身的路由表而實現網絡通訊。路由器在一份通告報文中能夠通告多個地址,而且給出每個地址的優先等級,這個優先等級是該IP做爲默認路由的等級,至於怎麼算的就不深究了。

    路由器通常會在450-600秒的時間間隔內發佈一次通告,而一個給定的通告報文的壽命是30分鐘。而主機在引導的時候會每三秒發送一次請求報文,一旦接受到一個有效的通告報文,就中止發送請求報文。

    TCP/IP詳解編寫的時候,只有Solaris2.x支持這兩種報文,大多數系統還不支持這兩種報文。(後面還會講到一些有用的路由報文)

    動態選路協議

    前面的選路方法叫作靜態選路,簡要地說就是在配置接口的時候,以默認的方式生成路由表項。並經過route來增長表項,或者經過ICMP報文來更新表項(一般在默認方式出錯的狀況下)。 而若是上訴三種方法都不能知足,那麼咱們就使用動態選路。

    動態選路協議是用於動態選路的重要組成部分,可是他們只是使用在路由器之間,相鄰路由器之間互相通訊。系統(路有選擇程序)選擇比較合適的路有放到核心路由表中,而後系統就能夠根據這個核心路有表找到最合適的網路。也就是說,動態選路是在系統核心網絡外部進行的,它只是用一些選路的策略影響路由表,而不會影響到最後經過路由表選擇路由的那一部分。選路協議有一大類經常使用的叫作內部網關協議(IGP),而在IGP中,RIP就是其中最重要的協議。一種新的IGP協議叫作開放最短路經優先(OSPF)協議,其意在取代RIP。另外一種最先用在網路骨幹網上的IGP協議--HELLO,如今已經不用了。

    現在,任何支持動態選路的路由器都必須同時支持OSPFRIP,還能夠選擇性的支持其餘的IGP協議。

    2.1.Unix選路程序

    Unix系統上面一般都有路由守護程序--routed。還有一個叫作gategate所支持的協議要比routed多,routed只是支持RIPv1版本。而gate則支持RIPv1v2BGPv1 等等。

    2.1.RIP:選路信息協議

    它的定義能夠在RFC1058內找到,這種協議使用UDP做爲載體(也就是UDP的上層協議)。咱們最關心的就是RIP其中的一個段,叫作度量的段,這是一個以hop做爲計數器(就是以走過多少路由爲計數器)的段(IP協議裏面也有一個TTL不是麼)。這個度量段將最終影響到路由表的創建。參考圖:

    通常說來routed要承擔以下的工做:

    1. 給每個已知的路由器發送rip請求報文,要求其餘路由器給出完整的路由表。這種報文的命令字段爲1,地址字段爲0,度量地段爲16(至關於無窮大)。
    2. 接受請求,若是接收到剛纔的那個請求,就把本身的完整的路由表交給請求者。若是沒有,就處理IP請求表項,把表項中本身有的部分添上跳數,沒有的部分添上16。而後發給請求者。
    3. 接受迴應。更新本身的路由表。使用hop數小的規則。
    4. 按期更新路由表,通常是30s(真頻繁)給相鄰的路有啓發一次本身的路由表。這種形式能夠使廣播形式的。

    這個協議看起來會工做的很好,可是,這裏面其實有不少隱藏的憂患,好比說RIP沒有子網的概念,好比說環路的危險。並且hop數的上限也限制了網絡的大小。

    所以,出現了不少RIPv1的替代品,好比說RIPv2,好比說OSPF。他們都是經過某種策略來影響路由表,因此就不說了。

    TCP/IP詳解學習筆記(6)-UDP協議

    1.UDP簡要介紹

    UDP是傳輸層協議,和TCP協議處於一個分層中,可是與TCP協議不一樣,UDP協議並不提供超時重傳,出錯重傳等功能,也就是說其是不可靠的協議。

    2.UDP協議頭

    2.1.UDP端口號

    因爲不少軟件須要用到UDP協議,因此UDP協議必須經過某個標誌用以區分不一樣的程序所須要的數據包。端口號的功能就在於此,例如某一個UDP程序A在系統中註冊了3000端口,那麼,之後從外面傳進來的目的端口號爲3000UDP包都會交給該程序。端口號理論上能夠有2^16這麼多。由於它的長度是16bit

    2.2.UDP檢驗和

    這是一個可選的選項,並非全部的系統都對UDP數據包加以檢驗和數據(相對TCP協議的必須來講),可是RFC中標準要求,發送端應該計算檢驗和。

    UDP檢驗和覆蓋UDP協議頭和數據,這和IP的檢驗和是不一樣的,IP協議的檢驗和只是覆蓋IP數據頭,並不覆蓋全部的數據。UDPTCP都包含一個僞首部,這是爲了計算檢驗和而攝製的。僞首部甚至還包含IP地址這樣的IP協議裏面都有的信息,目的是讓UDP兩次檢查數據是否已經正確到達目的地。若是發送端沒有打開檢驗和選項,而接收端計算檢驗和有差錯,那麼UDP數據將會被悄悄的丟掉(不保證送達),而不產生任何差錯報文。

    2.3.UDP長度

    UDP能夠很長很長,能夠有65535字節那麼長。可是通常網絡在傳送的時候,一次通常傳送不了那麼長的協議(涉及到MTU的問題),就只好對數據分片,固然,這些是對UDP等上級協議透明的,UDP不須要關心IP協議層對數據如何分片,下一個章節將會稍微討論一些分片的策略。

    3.IP分片

    IP在從上層接到數據之後,要根據IP地址來判斷從那個接口發送數據(經過選路),並進行MTU的查詢,若是數據大小超過MTU就進行數據分片。數據的分片是對上層和下層透明,而數據也只是到達目的地還會被從新組裝,不過不用擔憂,IP層提供了足夠的信息進行數據的再組裝。

    IP頭裏面,16bit識別號惟一記錄了一個IP包的ID,具備同一個IDIP片將會被從新組裝;而13位片偏移則記錄了某IP片相對整個包的位置;而這兩個表示中間的3bit標誌則標示着該分片後面是否還有新的分片。這三個標示就組成了IP分片的全部信息,接受方就能夠利用這些信息對IP數據進行從新組織(就算是後面的分片比前面的分片先到,這些信息也是足夠了)。

    由於分片技術在網絡上被常常的使用,因此僞造IP分片包進行流氓攻擊的軟件和人也就層出不窮。

    能夠用Trancdroute程序來進行簡單的MTU偵測。請參看教材。

    3.UDPARP之間的交互式用

    這是不常被人注意到的一個細節,這是針對一些系統地實現來講的。當ARP緩存仍是空的時候。UDP在被髮送以前必定要發送一個ARP請求來得到目的主機的MAC地址,若是這個UDP的數據包足夠大,大到IP層必定要對其進行分片的時候,想象中,該UDP數據包的第一個分片會發出一個ARP查詢請求,全部的分片都輝等到這個查詢完成之後再發送。事實上是這樣嗎?

    結果是,某些系統會讓每個分片都發送一個ARP查詢,全部的分片都在等待,可是接受到第一個迴應的時候,主機卻只發送了最後一個數據片而拋棄了其餘,這實在是讓人匪夷所思。這樣,由於分片的數據不能被及時組裝,接受主機將會在一段時間內將永遠沒法組裝的IP數據包拋棄,而且發送組裝超時的ICMP報文(其實不少系統不產生這個差錯),以保證接受主機本身的接收端緩存不被那些永遠得不到組裝的分片充滿。

    4.ICMP源站抑制差錯

    當目標主機的處理速度趕不上數據接收的速度,由於接受主機的IP層緩存會被佔滿,因此主機就會發出一個我受不了的一個ICMP報文。

    5.UDP服務器設計

    UDP協議的某些特性將會影響咱們的服務器程序設計,大體總結以下:

    1. 關於客戶IP和地址:服務器必須有根據客戶IP地址和端口號判斷數據包是否合法的能力(這彷佛要求每個服務器都要具有)
    2. 關於目的地址:服務器必需要有過濾廣播地址的能力。
    3. 關於數據輸入:一般服務器系統的每個端口號都會和一塊輸入緩衝區對應,進來的輸入根據先來後到的原則等待服務器的處理,因此不免會出現緩衝區溢出的問題,這種狀況下,UDP數據包可能會被丟棄,而應用服務器程序自己並不知道這個問題。
    4. 服務器應該限制本地IP地址,就是說它應該能夠把本身綁定到某一個網絡接口的某一個端口上。

    5.        

    6. TCP/IP詳解學習筆記(7)-廣播和多播,IGMP協議

    1.單播,多播,廣播的介紹

    1.1.單播(unicast)

    單播是說,對特定的主機進行數據傳送。例如給某一個主機發送IP數據包。這時候,數據鏈路層給出的數據頭裏面是很是具體的目的地址,對於以太網來 說,就是網卡的MAC地址(不是FF-FF-FF-FF-FF-FF這樣的地址)。如今的具備路由功能的主機應該能夠將單播數據定向轉發,而目的主機的網 絡接口則能夠過濾掉和本身MAC地址不一致的數據。

    1.2.廣播(unicast)

    廣播是主機針對某一個網絡上的全部主機發送數據包。這個網絡多是網絡,多是子網,還多是全部的子網。若是是網絡,例如A類網址的廣播就是 netid.255.255.255,若是是子網,則是netid.netid.subnetid.255;若是是全部的子網(BIP)則是則是 netid.netid.255.255。廣播所用的MAC地址FF-FF-FF-FF-FF-FF。網絡內全部的主機都會收到這個廣播數據,網卡只要把 MAC地址爲FF-FF-FF-FF-FF-FF的數據交給內核就能夠了。通常說來ARP,或者路由協議RIP應該是以廣播的形式播發的。

    1.3.多播(multicast)

    能夠說廣播是多播的特例,多播就是給一組特定的主機(多播組)發送數據,這樣,數據的播發範圍會小一些(實際上播發的範圍一點也沒有變小),多播的MAC地址是最高字節的低位爲一,例 01-00-00-00-00-00。多播組的地址是DIP,規定是224.0.0.0-239.255.255.255

    雖然多播比較特殊,可是究其原理,多播的數據仍是要經過數據鏈路層進行MAC地址綁定而後進行發送。因此一個以太網卡在綁定了一個多播IP地址以後,必 定還要綁定一個多播的MAC地址,才能使得其能夠像單播那樣工做。這個多播的IP和多播MAC地址有一個對應的算法,在書的p133p134之間。能夠看到 這個對應不是一一對應的,主機仍是要對多播數據進行過濾。

    我的的見解:廣播和多播的性質是同樣的,路由器會把數據放到局域網裏面,而後網卡對這些數據進行過濾,只拿到本身打算要的數據,好比本身感興趣的多 播數據,本身感興趣的組播數據。當一個主機運行了一個處理某一個多播IP的進程的時候,這個進程會給網卡綁定一個虛擬的多播mac地址,並作出來一個多播 ip。這樣,網卡就會讓帶有這個多播mac地址的數據進來,從而實現通訊,而那些沒有監聽這些數據的主機就會把這些數據過濾掉,換句話說,多播,是讓主機 的內核輕鬆了,而網卡,對不起,您就累點吧。

    一些文章也印證了這種想法,最明顯的就是局域網監聽的原理、實現與防範

    2.一些驗證性實驗

    這些實驗並非很複雜,咱們只是要ping一下通常的ip和一個廣播地址。首先我ping一下本身所在的子網的某一臺主機:

    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time=1ms TTL=255

    能夠看到,機器返回的是一臺主機的迴應結果,進而推測,若是我ping一個廣播地址呢?結果以下

    Reply from 192.168.11.9: bytes=32 time=1ms TTL=255
    Reply from 192.168.11.174: bytes=32 time<1ms TTL=64
    Reply from 192.168.11.174: bytes=32 time<1ms TTL=64
    Reply from 192.168.11.174: bytes=32 time<1ms TTL=64
    Reply from 192.168.11.218: bytes=32 time<1ms TTL=64
    Reply from 192.168.11.174: bytes=32 time<1ms TTL=64

    能夠看到,ping返回了一些隨機的ip的結果,這些ip都是與主機在同一子網內的ip。咱們能夠看到,廣播其實是給處於子網內的全部ip發信。

    再來一個多播的例子,可是要實現這個多播並不容易,由於我不知道網絡內有多少個多播組,就只好利用幾個特殊的多播地址來驗證了。

    對於多播地址,有幾個特殊的多播地址被佔用,他們是

    1. 224.0.0.1--該子網內全部的系統組。
    2. 224.0.0.2--該子網內全部的路由器。
    3. 224.0.1.1--網絡實現協議NTP專用IP
    4. 224.0.0.9--RIPv2專用IP

    因此只要ping這幾個IP,就應該能獲得一些結果,好比說我ping 224.0.0.2

    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255
    Reply from 192.168.11.1: bytes=32 time<1ms TTL=255

    咱們能夠看到,這回ping只返回了一個ip的迴應。而這個就是個人網關的地址,這也驗證了224.0.0.2是全部路由器的多播(組播)地址

    3.IGMP協議

    IGMP的做用在於,讓其餘全部須要知道本身處於哪一個多播組的主機和路由器知道本身的狀態。通常多播路由器根本不須要知道某一個多播組裏面有多少個主機,而只要知道本身的子網內還有沒有處於某個多播組的主機就能夠了。只要某一個多播組還有一臺主機,多播路由器就會把數據傳輸出去,這樣,接受方就會經過網卡過濾功能來獲得本身想要的數據。爲了知道多播組的信息,多播路由器須要定時的發送IGMP查詢,IGMP的格式能夠看書,各個多播組裏面的主機要根據查詢來回複本身的狀態。路由器來決定有幾個多播組,本身要對某一個多播組發送什麼樣的數據。

    這種查詢迴應數據報的TTL通常是1,並且就算是出錯也不產生ICMP差錯(不必)。

     

    TCP/IP詳解學習筆記(8)-DNS域名系統

    前面已經提到了訪問一臺機器要靠IP地址和MAC地址,其中,MAC地址能夠經過ARP協議獲得,因此這對用戶是透明的,可是IP地址就不行,不管如何用戶都須要用一個指定的IP來訪問一臺計算機,而IP地址又很是很差記,因而就出現了DNS系統

    1.DNS系統介紹

    DNS的全稱是Domain Name System。它負責把FQDN(就是以"."分隔結尾的名字)翻譯成一個IP。最初的DNS系統使用的是一個巨大的hosts.txt文件(很吃驚,用 這個就好使了?),但是一段時間之後,開發這就不得不用數據庫來代替hosts.txt文件,最終發展到瞭如今的分佈式數據庫。

    從書中的143頁能夠看到,DNS系統是一個巨大的樹,最上方有一個無名樹根,下一層是arpa,com,edu,gov,int,milus, cn。等等,其中arpa,是域名反解析樹的頂端;而comedu,等域名原本只用在美國(這就是技術特權啊),可是如今幾乎全世界通用;而us cn,等叫作國家域。這個樹裏面的域名並非統一管理的,網絡信息中心(NIS)負責分配頂級域合委派其餘制定地區域的受權機構。

    一個獨立管理的DNS子樹叫作zone,最多見的區域就是二級域名,好比說.com.cn。咱們還能夠把這個二級域名給劃分紅更小的區域,好比說sina.com.cn

    DNS系統是一個分佈式的數據庫,當一個數據庫發現本身並無某查詢所須要的數據的時候,它將把查詢轉發出去,而轉發的目的地一般是根服務器,根服 務器從上至下層層轉發查詢,直到找到目標爲止。DNS還有一個特色就是使用高速緩存,DNS把查詢過的數據緩存在某處,以便於下次查詢時使用。

    2.DNS協議

    DNS報文定義了一個既能夠查詢也能夠響應的報文格式。具體格式能夠看P145頁。對各個字段簡單解釋以下

    1. 最前面的16bit惟一的標示了問題號碼,用於查詢端區別本身的查詢。
    2. 緊接着的16bit又能夠作進一步的細分,標示了報文的性質和一些細節,好比說是查詢報文仍是響應報文,須要遞歸查詢與否(通常服務器都支持遞歸查詢,並且不須要任何設置,BIND就是這樣)
    3. 查詢問題後面有查詢類型,包括ANSCNAMEPTRHINFOMX,若是熟悉BIND的話,就知道在zong的配置文件裏面,每一條記錄都記載了各自的類型,好比A就是IP地址,NS就是名字服務器。
    4. 響應報文能夠回覆多個IP,也就是說,域名能夠和多個IP地址對應,而且有不少CNAME

    3.反向查詢

    正向查詢指的是經過域名獲得IP的查詢,而反向查詢就是經過IP獲得域名。例如用host命令,host ip就能夠獲得服務器的域名,host domainName 就獲得IP

    稍微知道一點數據結構的人都能意識到,在正向查詢的域裏面作反向查詢,其作法只有遍歷整個數據集合----對於DNS來講,那就是遍歷整個數據庫, 這將帶來巨大的負擔,因此DNS採起了另外一種方法,使用另外一棵子樹來維護IP-〉域名的對應表。這個子樹的根節點是in-addr.arpa,而一個IP 例如192.168.11.2)所具備的DNS地址就是 2.11.168.192.in-addr.arpaip倒置)。在DNS系統裏面,一個反向地址對應一個PTR紀錄(對應A紀錄),因此反向查詢又叫 作指針(PTR)查詢。

    4.其餘問題的討論

    4.1.DNS服務器高速緩存

    BIND9默認是做爲一個高速緩存服務器,其將全部的查詢都轉交到根服務器去,而後獲得結果並放在本地的緩衝區,以加快查詢速度。若是有興趣能夠安裝一個BIND9來嘗試一下。而本身定義的zone則能夠規定其在緩存中的時間,通常是1天(就是配置文件中的1D)。

    4.2.UDP仍是TCP

    DNS服務器支持TCPUDP兩種協議的查詢方式,並且端口都是53。而大多數的查詢都是UDP查詢的,通常須要TCP查詢的有兩種狀況:

    1. 當查詢數據多大以致於產生了數據截斷(TC標誌爲1),這時,須要利用TCP的分片能力來進行數據傳輸(看TCP的相關章節)。
    2. 當主(master)服務器和輔(slave)服務器之間通訊,輔服務器要拿到主服務器的zone信息的時候。

     

    TCP/IP詳解學習筆記(9)-TCP協議概述

    終於看到了TCP協議,這是TCP/IP詳解裏面最重要也是最精彩的部分,要花大力氣來讀。前面的TFTPBOOTP都是一些簡單的協議,就不寫筆記了,寫起來也沒啥東西。

    TCPUDP處在同一層---運輸層,可是TCPUDP最不一樣的地方是,TCP提供了一種可靠的數據傳輸服務,TCP是面向鏈接的,也就是說,利用TCP通訊的兩臺主機首先要經歷一個撥打電話的過程,等到通訊準備結束纔開始傳輸數據,最後結束通話。因此TCP要比UDP可靠的多,UDP是把數據直接發出去,而無論對方是否是在收信,就算是UDP沒法送達,也不會產生ICMP差錯報文,這一經時重申了不少遍了。

    TCP保證可靠性的簡單工做原理摘抄以下

    • 應用數據被分割成TCP認爲最適合發送的數據塊。這和UDP徹底不一樣,應用程序產生的 數據報長度將保持不變。由TCP傳遞給IP的信息單位稱爲報文段或段( segment)(參見圖1 - 7)。在1 8.4節咱們將看到TCP如何肯定報文段的長度。
    • TCP發出一個段後,它啓動一個定時器,等待目的端確認收到這個報文段。若是不能 及時收到一個確認,將重發這個報文段。在第21章咱們將瞭解TCP協議中自適應的超時 及重傳策略。
    • TCP收到發自TCP鏈接另外一端的數據,它將發送一個確認。這個確認不是當即發送,一般將推遲幾分之一秒,這將在1 9.3節討論。
    • TCP將保持它首部和數據的檢驗和。這是一個端到端的檢驗和,目的是檢測數據在傳輸 過程當中的任何變化。若是收到段的檢驗和有差錯, T P將丟棄這個報文段和不確認收到此報文段(但願發端超時並重發)。
    • 既然TCP報文段做爲IP數據報來傳輸,而IP數據報的到達可能會失序,所以TCP報文段 的到達也可能會失序。若是必要, TCP將對收到的數據進行從新排序,將收到的數據以正確的順序交給應用層。
    • TCP還能提供流量控制。TCP鏈接的每一方都有固定大小的緩衝空間。TCP的接收端只容許另外一端發送接收端緩衝區所能接納的數據。這將防止較快主機導致較慢主機的緩衝區溢出。

    從這段話中能夠看到,TCP中保持可靠性的方式就是超時重發,這是有道理的,雖然TCP也能夠用各類各樣的ICMP報文來處理這些,可是這也不是可靠的,最可靠的方式就是隻要不獲得確認,就從新發送數據報,直到獲得對方的確認爲止。

    TCP的首部和UDP首部同樣,都有發送端口號和接收端口號。可是顯然,TCP的首部信息要比UDP的多,能夠看到,TCP協議提供了發送和確認所須要的全部必要的信息。這在P171-173有詳細地介紹。能夠想象一個TCP數據的發送應該是以下的一個過程。

    • 雙方創建鏈接
    • 發送方給接受方TCP數據報,而後等待對方的確認TCP數據報,若是沒有,就從新發,若是有,就發送下一個數據報。
    • 接受方等待發送方的數據報,若是獲得數據報並檢驗無誤,就發送ACK(確認)數據報,並等待下一個TCP數據報的到來。直到接收到FIN(發送完成數據報)
    • 停止鏈接

    能夠想見,爲了創建一個TCP鏈接,系統可能會創建一個新的進程(最差也是一個線程),來進行數據的傳送

    TCP/IP詳解學習筆記(10)-TCP鏈接的創建與停止

    TCP是一個面向鏈接的協議,因此在鏈接雙方發送數據以前,都須要首先創建一條鏈接。這和前面講到的協議徹底不一樣。前面講的全部協議都只是發送數據而已,大多數都不關心發送的數據是否是送到,UDP尤爲明顯,從編程的角度來講,UDP編程也要簡單的多----UDP都不用考慮數據分片。

    書中用telnet登錄退出來解釋TCP協議鏈接的創建和停止的過程,能夠看到,TCP鏈接的創建能夠簡單的稱爲三次握手,而鏈接的停止則能夠叫作四次握手

    1.鏈接的創建

    在創建鏈接的時候,客戶端首先向服務器申請打開某一個端口(SYN段等於1TCP報文),而後服務器端發回一個ACK報文通知客戶端請求報文收到,客戶端收到確認報文之後再次發出確認報文確認剛纔服務器端發出的確認報文(繞口麼),至此,鏈接的創建完成。這就叫作三次握手。若是打算讓雙方都作好準備的話,必定要發送三次報文,並且只須要三次報文就能夠了。

    能夠想見,若是再加上TCP的超時重傳機制,那麼TCP就徹底能夠保證一個數據包被送到目的地。

    2.結束鏈接

    TCP有一個特別的概念叫作half-close,這個概念是說,TCP的鏈接是全雙工(能夠同時發送和接收)鏈接,所以在關閉鏈接的時候,必須關閉傳和送兩個方向上的鏈接。客戶機給服務器一個FIN1TCP報文,而後服務器返回給客戶端一個確認ACK報文,而且發送一個FIN報文,當客戶機回覆ACK報文後(四次握手),鏈接就結束了。

    3.最大報文長度

    在創建鏈接的時候,通訊的雙方要互相確認對方的最大報文長度(MSS),以便通訊。通常這個SYN長度是MTU減去固定IP首部和TCP首部長度。對於一個以太網,通常能夠達到1460字節。固然若是對於非本地的IP,這個MSS可能就只有536字節,並且,若是中間的傳輸網絡的MSS更佳的小的話,這個值還會變得更小。

    3.   TCP的狀態遷移圖

    下面的文章按照client/server兩條路線講述TCP狀態遷移路線圖。

     

    P182頁給出了TCP的狀態圖,這是一個看起來比較複雜的狀態遷移圖,由於它包含了兩個部分---服務器的狀態遷移和客戶端的狀態遷移,若是從某一個角度出發來看這個圖,就會清晰許多,這裏面的服務器和客戶端都不是絕對的,發送數據的就是客戶端,接受數據的就是服務器。

       1. 鏈接創建

       1) Client

    Client端調用socket函數調用時,至關於Client端產生了一個處於Closed狀態的套接字。

    Client端又調用connect函數調用,系統爲Client隨機分配一個端口,連同傳入connect中的參數(ServerIP和端口),這就造成了一個鏈接四元組,connect調用讓Client端的socket處於SYN_SENT狀態

    Server返回確認,併發送SYNClient返回確認及SYN後,套接字處於ESTABLISHED階段,此時雙方的鏈接已經能夠進行讀寫操做

       2)Server

    Server端調用socket函數調用時,至關於Server端產生了一個處於Closed狀態的監聽套接字.

    Server端調用bind操做,將監聽套接字與指定的地址和端口關聯,而後又調用listen函數,系統會爲其分配未完成隊列和完成隊列,此時的監聽套接字能夠接受Client的鏈接,監聽套接字狀態處於LISTEN狀態。

    Server端調用accept操做時,會從完成隊列中取出一個已經完成的client鏈接,同時在server這段會產生一個會話套接字,用於和client端套接字的通訊,這個會話套接字的狀態是ESTABLISH

       2. 鏈接關閉

    與鏈接創建分爲server/client不一樣,鏈接關閉並無絕對的server/client之分,鏈接關閉分爲主動關閉和被動關閉。Serverclient均可以擔任這兩個角色中的任意一個。如client能夠關閉它與server的鏈接,一樣的server同樣也能夠關閉一些長時間無讀寫事件發生的鏈接。既然這麼說了,下面就會分紅兩個部分:client主動關閉,server主動關閉。

     

    Client主動關閉,Server被動關閉:

    Client主動關閉,Server被動關閉的狀況仍是蠻多的,好比說短鏈接中,當一次會話結束時,client就能夠關閉它與server之間的鏈接。咱們這邊直接說close而非shutdown

    client想要關閉它與server之間的鏈接,首先client這邊會首先調用close函數,client端會發送一個FINserver端,client端處於FIN_WAIT1狀態。當server端返回給client ACK後,client處於FIN_WAIT2狀態,server處於CLOSE_WAIT狀態。

    server端檢測到client端的關閉操做(read返回爲0)server端也須要調用close操做,server端會向client端發送一個FIN。此時server的狀態爲LAST_ACK,當client收到來自serverFIN後,client端的套接字處於TIME_WAIT狀態,它會向server端再發送一個ack確認,此時server端收到ack確認後,此套接字處於CLOSED狀態。

     

    Server端主動關閉的流程與Client端關閉相似,就再也不多講,下面還須要關注的是TIME_WAIT這個狀態,分別按照client/server兩個部分講述。

    首先說一下TCP/IP詳解中描述的關於TIME_WAIT的描述及其存在的必要性:

    主動關閉的socket當收到對端的FIN操做後,該socket就會處於TIME_WAIT狀態,處於TIME_WAIT狀態的socket會存活2MSL(Max Segment Lifetime),之因此存活這麼長時間是有理由的:

    一方面是可靠的實現TCP全雙工鏈接的終止,也就是當最後的ACK丟失後,被動關閉端會重發FIN,所以主動關閉端須要維持狀態信息,以容許它從新發送最終的ACK

    另外一方面TCP2MSL等待期間,定義這個鏈接(4元組)不能再使用,任何遲到的報文都會丟棄。設想若是沒有2MSL的限制,剛好新到的鏈接正好知足原先的4元組,這時候鏈接就可能接收到網絡上的延遲報文就可能干擾最新創建的鏈接。

    另外一方面是爲了重複的分節在網絡中消逝。對於

    另外一方面是網絡上仍然可能有殘餘的數據包

    Client主動關閉時,正常狀況下clientsocket會經歷TIME_WAIT的狀態

    鏈接在關閉的時候,雙方都會有狀態的遷移,這就要求咱們的程序中必定要有比較徹底的

       3. Server端的監聽套接字與會話套接字的不一樣:

    server端的socket調用bindlisten以後,監聽套接字的狀態就會變爲LISTEN狀態,監聽套接字的工做決定了它只是監聽鏈接。

    server端調用accept,至關於從套接字的完成隊列中取出一個client的鏈接,此時能夠肯定四元組,即:clientIPportserverIPport,雙方各有一個套接字進行交互,這裏須要說一下server端的socket,我稱serveraccept後產生的套接字爲會話套接字,這個套接字一出生的狀態就是ESTABLISH

    server端得四元組咱們能夠看出,一個server從理論上能夠接收的鏈接數量取決於文件描述符的個數。

    4.1.客戶端應用程序的狀態遷移圖

    客戶端的狀態能夠用以下的流程來表示:

    CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

    以上流程是在程序正常的狀況下應該有的流程,從書中的圖中能夠看到,在創建鏈接時,當客戶端收到SYN報文的ACK之後,客戶端就打開了數據交互地鏈接。而結束鏈接則一般是客戶端主動結束的,客戶端結束應用程序之後,須要經歷FIN_WAIT_1FIN_WAIT_2等狀態,這些狀態的遷移就是前面提到的結束鏈接的四次握手。

    4.2.服務器的狀態遷移圖

    服務器的狀態能夠用以下的流程來表示:

    CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED

    在創建鏈接的時候,服務器端是在第三次握手以後才進入數據交互狀態,而關閉鏈接則是在關閉鏈接的第二次握手之後(注意不是第四次)。而關閉之後還要等待客戶端給出最後的ACK包才能進入初始的狀態。

    4.3.其餘狀態遷移

    書中的圖還有一些其餘的狀態遷移,這些狀態遷移針對服務器和客戶端兩方面的總結以下

    1. LISTEN->SYN_SENT,對於這個解釋就很簡單了,服務器有時候也要打開鏈接的嘛。
    2. SYN_SENT->SYN收到,服務器和客戶端在SYN_SENT狀態下若是收到SYN數據報,則都須要發送SYNACK數據報並把本身的狀態調整到SYN收到狀態,準備進入ESTABLISHED
    3. SYN_SENT->CLOSED,在發送超時的狀況下,會返回到CLOSED狀態。
    4. SYN_收到->LISTEN,若是受到RST包,會返回到LISTEN狀態。
    5. SYN_收到->FIN_WAIT_1,這個遷移是說,能夠不用到ESTABLISHED狀態,而能夠直接跳轉到FIN_WAIT_1狀態並等待關閉。

    4.4.2MSL等待狀態

    書中給的圖裏面,有一個TIME_WAIT等待狀態,這個狀態又叫作2MSL狀態,說的是在TIME_WAIT2發送了最後一個ACK數據報之後,要進入TIME_WAIT狀態,這個狀態是防止最後一次握手的數據報沒有傳送到對方那裏而準備的(注意這不是四次握手,這是第四次握手的保險狀態)。這個狀態在很大程度上保證了雙方均可以正常結束,可是,問題也來了。

    因爲插口的2MSL狀態(插口是IP和端口對的意思,socket),使得應用程序在2MSL時間內是沒法再次使用同一個插口的,對於客戶程序還好一些,可是對於服務程序,例如httpd,它老是要使用同一個端口來進行服務,而在2MSL時間內,啓動httpd就會出現錯誤(插口被使用)。爲了不這個錯誤,服務器給出了一個平靜時間的概念,這是說在2MSL時間內,雖然能夠從新啓動服務器,可是這個服務器仍是要平靜的等待2MSL時間的過去才能進行下一次鏈接。

    4.5.FIN_WAIT_2狀態

    這就是著名的半關閉的狀態了,這是在關閉鏈接時,客戶端和服務器兩次握手以後的狀態。在這個狀態下,應用程序還有接受數據的能力,可是已經沒法發送數據,可是也有一種多是,客戶端一直處於FIN_WAIT_2狀態,而服務器則一直處於WAIT_CLOSE狀態,而直到應用層來決定關閉這個狀態。

    5.RST,同時打開和同時關閉

    RST是另外一種關閉鏈接的方式,應用程序應該能夠判斷RST包的真實性,便是否爲異常停止。而同時打開和同時關閉則是兩種特殊的TCP狀態,發生的機率很小。

    6.TCP服務器設計

    前面曾經講述過UDP的服務器設計,能夠發現UDP的服務器徹底不須要所謂的併發機制,它只要創建一個數據輸入隊列就能夠。可是TCP不一樣,TCP服務器對於每個鏈接都須要創建一個獨立的進程(或者是輕量級的,線程),來保證對話的獨立性。因此TCP服務器是併發的。並且TCP還須要配備一個呼入鏈接請求隊列(UDP服務器也一樣不須要),來爲每個鏈接請求創建對話進程,這也就是爲何各類TCP服務器都有一個最大鏈接數的緣由。而根據源主機的IP和端口號碼,服務器能夠很輕鬆的區別出不一樣的會話,來進行數據的分發。

    掌握本章的狀態遷移圖纔是學習本章的關鍵。

    TCP/IP詳解學習筆記(11)-TCP交互數據流,成塊數據流

    目前創建在TCP協議上的網絡協議特別多,有telnetssh,有ftp,有http等等。這些協議又能夠根據數據吞吐量來大體分紅兩大類:(1)交互數據類型,例如telnetssh,這種類型的協議在大多數狀況下只是作小流量的數據交換,好比說按一下鍵盤,回顯一些文字等等。(2)數據成塊類型,例如ftp,這種類型的協議要求TCP能儘可能的運載數據,把數據的吞吐量作到最大,並儘量的提升效率。針對這兩種狀況,TCP給出了兩種不一樣的策略來進行數據傳輸。

    1.TCP的交互數據流

    對於交互性要求比較高的應用,TCP給出兩個策略來提升發送效率和減低網絡負擔:(1)捎帶ACK(2)Nagle算法(一次儘可能多的發數據)。一般,在網絡速度很快的狀況下,好比用lo接口進行telnet通訊,當按下字母鍵並要求回顯的時候,客戶端和服務器將經歷 發送按鍵數據->服務器發送按鍵數據的ack -> 服務器端發送回顯數據->客戶端發送回顯數據的ACK的過程,而其中的數據流量將是40bit + 41bit+41bit+40bit = 162bit,若是在廣域網裏面,這種小分組的TCP流量將會形成很大的網絡負擔。

    1.1.捎帶ACK的發送方式

    這個策略是說,當主機收到遠程主機的TCP數據報以後,一般不立刻發送ACK數據報,而是等上一個短暫的時間,若是這段時間裏面主機還有發送到遠程主機的TCP數據報,那麼就把這個ACK數據報捎帶着發送出去,把原本兩個TCP數據報整合成一個發送。通常的,這個時間是200ms。能夠明顯地看到這個策略能夠把TCP數據報的利用率提升不少。

    1.2.Nagle算法

    上過bbs的人應該都會有感覺,就是在網絡慢的時候發貼,有時鍵入一串字符串之後,通過一段時間,客戶端發瘋同樣忽然回顯出不少內容,就好像數據一會兒傳過來了同樣,這就是Nagle算法的做用。

    Nagle算法是說,當主機A給主機B發送了一個TCP數據報並進入等待主機BACK數據報的狀態時,TCP的輸出緩衝區裏面只能有一個TCP數據報,而且,這個數據報不斷地收集後來的數據,整合成一個大的數據報,等到B主機的ACK包一到,就把這些數據一股腦的發送出去。雖然這樣的描述有些不許確,但還算形象和易於理解,咱們一樣能夠體會到這個策略對於低減網絡負擔的好處。

    在編寫插口程序的時候,能夠經過TCP_NODELAY來關閉這個算法。而且,使用這個算法看狀況的,好比基於TCPX窗口協議,若是處理鼠標事件時仍是用這個算法,那麼延遲可就很是大了。

    2.TCP的成塊數據流

    對於FTP這樣對於數據吞吐量有較高要求的要求,將老是但願每次儘可能多的發送數據到對方主機,就算是有點延遲也無所謂。TCP也提供了一整套的策略來支持這樣的需求。TCP協議中有16bit表示窗口的大小,這是這些策略的核心。

    2.1.傳輸數據時ACK的問題

    在解釋滑動窗口前,須要看看ACK的應答策略,通常來講,發送端發送一個TCP數據報,那麼接收端就應該發送一個ACK數據報。可是事實上卻不是這樣,發送端將會連續發送數據儘可能填滿接受方的緩衝區,而接受方對這些數據只要發送一個ACK報文來回應就能夠了,這就是ACK的累積特性,這個特性大大減小了發送端和接收端的負擔。

    2.2.滑動窗口

    滑動窗口本質上是描述接受方的TCP數據報緩衝區大小的數據,發送方根據這個數據來計算本身最多能發送多長的數據。若是發送方收到接受方的窗口大小爲0TCP數據報,那麼發送方將中止發送數據,等到接受方發送窗口大小不爲0的數據報的到來。書中的P211P212很好的解釋了這一點。

    關於滑動窗口協議,書上還介紹了三個術語,分別是:

    1. 窗口合攏:當窗口從左邊向右邊靠近的時候,這種現象發生在數據被髮送和確認的時候。
    2. 窗口張開:當窗口的右邊沿向右邊移動的時候,這種現象發生在接受端處理了數據之後。
    3. 窗口收縮:當窗口的右邊沿向左邊移動的時候,這種現象不常發生。

    TCP就是用這個窗口,慢慢的從數據的左邊移動到右邊,把處於窗口範圍內的數據發送出去(但不用發送全部,只是處於窗口內的數據能夠發送。)。這就是窗口的意義。圖20-6解釋了這一點。窗口的大小是能夠經過socket來制定的,4096並非最理想的窗口大小,而16384則能夠使吞吐量大大的增長。

    2.3.數據擁塞

    上面的策略用於局域網內傳輸還能夠,可是用在廣域網中就可能會出現問題,最大的問題就是當傳輸時出現了瓶頸(好比說必定要通過一個slip低速鏈路)所產生的大量數據堵塞問題(擁塞),爲了解決這個問題,TCP發送方須要確認鏈接雙方的線路的數據最大吞吐量是多少。這,就是所謂的擁塞窗口。

    擁塞窗口的原理很簡單,TCP發送方首先發送一個數據報,而後等待對方的迴應,獲得迴應後就把這個窗口的大小加倍,而後連續發送兩個數據報,等到對方迴應之後,再把這個窗口加倍(先是2的指數倍,到必定程度後就變成現行增加,這就是所謂的慢啓動),發送更多的數據報,直到出現超時錯誤,這樣,發送端就瞭解到了通訊雙方的線路承載能力,也就肯定了擁塞窗口的大小,發送方就用這個擁塞窗口的大小發送數據。要觀察這個現象是很是容易的,咱們通常在下載數據的時候,速度都是慢慢衝起來的

    以上就是TCP數據傳輸的大體流程,雖然並不細緻,可是足以描述TCP的工做原理,重點是TCP的流量控制原理,滑動窗口,擁塞窗口,ACK累計確認等知識點。

    TCP/IP詳解學習筆記(12)-TCP的超時與重傳

    超時重傳是TCP協議保證數據可靠性的另外一個重要機制,其原理是在發送某一個數據之後就開啓一個計時器,在必定時間內若是沒有獲得發送的數據報的ACK報文,那麼就從新發送數據,直到發送成功爲止。

    1.超時

    超時時間的計算是超時的核心部分,TCP要求這個算法能大體估計出當前的網絡情況,雖然這確實很困難。要求精確的緣由有兩個:(1)定時長久會形成網絡利用率不高。(2)定時過短會形成屢次重傳,使得網絡阻塞。因此,書中給出了一套經驗公式,和其餘的保證計時器準確的措施。

    1.1.遞推公式概說

    最先的TCP曾經用了一個很是簡單的公式來估計當前網絡的情況,以下

    R<-aR+(1-a)M

    RTP=Rb

    其中a是一個經驗係數爲0.1b一般爲2。注意,這是經驗,沒有推導過程,這個數值是能夠被修改的。這個公式是說用舊的RTT(R)和新的RTT(M)綜合到一塊兒來考慮新的RTT(R)的大小。可是,咱們又看到,這種估計在網絡變化很大的狀況下徹底不能作出靈敏的反應Jacoboson說的,不是偶說的,呵呵),因而就有下面的修正公式:

    Err=M-A

    A<-A+gErr

    D<-D+h(|Err|-D)

    RTO=A+4D

    具體的解釋請看書的228頁,這個遞推公式甚至把方差這種統計概念也使用了進來,使得誤差更加的小。並且,必需要指出的是,這兩組公式更新,都是在數據成功傳輸的狀況下才進行,在發生數據從新傳輸的狀況下,並不使用上面的公式進行網絡估計,理由很簡單,由於程序已經不在正常狀態下了,估計出來的數據也是沒有意義的。

    1.2.RTO的初始化

    RTO的初始化是由公式決定的,例如最初的公式,初始的值應該是1。而修正公式,初始RTO應該是A+4D

    1.3.RTO的更新

    當數據正常傳輸的狀況下,咱們就會用上面的公式來更新各個數據,並重開定時器,來保證下一個數據被順利傳輸。要注意的是:重傳的狀況下,RTO不用上面的公式計算,而採用一種叫作指數退避的方式。例如:當RTO1S的狀況下,發生了數據重傳,咱們就用RTO=2S的定時器來從新傳輸數據,下一次用4S。一直增長到64S爲止。

    1.4.估計器的初始化

    在這裏,SYN用的估計器初始化彷佛和傳輸用的估計器不同(我也沒有把握)造個人理解,在修正公式中,SYN的狀況下,A初始化爲0,D初始化爲3S

    而在獲得傳輸第一個數據的ACK的時候,應該按照下面的公式進行初始化:

    A=M+0.5

    D=A/2

    1.5.估計器的更新

    和上面的討論差很少,就是在正常狀況下,用上面的公式計算,在重傳的狀況下,不更新估計器的各類參數。緣由仍是由於估計不許確。

    1.6.Karn算法

    這不算是一個算法,這應該是一個策略,說的就是更新RTO和估計器的值的時機選擇問題,1.3.1.5.所說得更新時機就是Karn算法。

    1.7.計時器的使用

    兩句話:

    1. 一個鏈接中,有且僅有一個測量定時器被使用。也就是說,若是TCP連續發出3組數據,只有一組數據會被測量。
    2. ACK數據報不會被測量,緣由很簡單,沒有ACKACK迴應能夠供結束定時器測量。

    2.重傳

    有了超時就要有重傳,可是就算是重傳也是有策略的,而不是將數據簡單的發送。

    2.1.重傳時發送數據的大小

    前面曾經提到過,數據在傳輸的時候不能只使用一個窗口協議,咱們還須要有一個擁塞窗口來控制數據的流量,使得數據不會一會兒都跑到網路中引發擁塞。也曾經提到過,擁塞窗口最初使用指數增加的速度來增長自身的窗口,直到發生超時重傳,再進行一次微調。可是沒有提到,如何進行微調,擁塞避免算法和慢啓動門限就是爲此而生。

    所謂的慢啓動門限就是說,當擁塞窗口超過這個門限的時候,就使用擁塞避免算法,而在門限之內就採用慢啓動算法。因此這個標準才叫作門限,一般,擁塞窗口記作cwnd,慢啓動門限記作ssthresh。下面咱們來看看擁塞避免和慢啓動是怎麼一塊兒工做的

    算法概要(直接從書中拷貝)

    1. 對一個給定的鏈接,初始化cwnd1個報文段,ssthresh65535個字節。
    2. TCP輸出例程的輸出不能超過cwnd和接收方通告窗口的大小。擁塞避免是發送方使用 的流量控制,而通告窗口則是接收方進行的流量控制。前者是發送方感覺到的網絡擁塞的估 計,然後者則與接收方在該鏈接上的可用緩存大小有關。
    3. 當擁塞發生時(超時或收到重複確認),ssthresh被設置爲當前窗口大小的一半(cwnd 和接收方通告窗口大小的最小值,但最少爲2個報文段)。此外,若是是超時引發了擁塞,則 cwnd被設置爲1個報文段(這就是慢啓動)。
    4. 當新的數據被對方確認時,就增長cwnd,但增長的方法依賴於咱們是否正在進行慢啓 動或擁塞避免。若是cwnd小於或等於ssthresh,則正在進行慢啓動,不然正在進行擁塞避免。 慢啓動一直持續到咱們回到當擁塞發生時所處位置的半時候才中止(由於咱們記錄了在步驟2 中給咱們製造麻煩的窗口大小的一半),而後轉爲執行擁塞避免。

    補充上面的擁塞避免公式在P238頁。這整個的流程讓我聯想到開車換檔的過程。

    2.2.快速重傳和快速恢復算法

    這是數據丟包的狀況下給出的一種修補機制。通常來講,重傳發生在超時以後,可是若是發送端接受到3個以上的重複ACK的狀況下,就應該意識到,數據丟了,須要從新傳遞。這個機制是不須要等到重傳定時器溢出的,因此叫作快速重傳,而從新傳遞之後,由於走的不是慢啓動而是擁塞避免算法,因此這又叫作快速恢復算法。流程以下:

    1. 當收到第3個重複的ACK時,將ssthresh設置爲當前擁塞窗口cwnd的一半。重傳丟失的 報文段。設置cwndssthresh加上3倍的報文段大小。
    2. 每次收到另外一個重複的ACK時, cwnd增長1個報文段大小併發送1個分組(若是新的 cwnd容許發送)。
    3. 當下一個確認新數據的ACK到達時,設置cwndssthresh(在第1步中設置的值)。這個 ACK應該是在進行重傳後的一個往返時間內對步驟1中重傳的確認。另外,這個ACK也應該 是對丟失的分組和收到的第1個重複的ACK之間的全部中間報文段的確認。這一步採用的是擁 塞避免,由於當分組丟失時咱們將當前的速率減半。

    2.3.ICMP會引發從新傳遞麼?

    答案是:不會TCP會堅持用本身的定時器,可是TCP會保留下ICMP的錯誤而且通知用戶。

    2.4.從新分組

    TCP爲了提升本身的效率,容許再從新傳輸的時候,只要傳輸包含重傳數據報文的報文就能夠,而不用只重傳須要傳輸的報文。

    TCP/IP詳解學習筆記(13)-TCP堅持定時器,TCP保活定時器

    TCP一共有四個主要的定時器,前面已經講到了一個--超時定時器--是TCP裏面最複雜的一個,另外的三個是:

    1. 堅持定時器
    2. 保活定時器
    3. 2MSL定時器

    其中堅持定時器用於防止通告窗口爲0之後雙方互相等待死鎖的狀況;而保活定時器則用於處理半開放鏈接

    1.堅持定時器

    堅持定時器的原理是簡單的,當TCP服務器收到了客戶端的0滑動窗口報文的時候,就啓動一個定時器來計時,並在定時器溢出的時候向向客戶端查詢窗口是否已經增大,若是獲得非零的窗口就從新開始發送數據,若是獲得0窗口就再開一個新的定時器準備下一次查詢。經過觀察能夠得知,TCP的堅持定時器使用124816……64秒這樣的普通指數退避序列來做爲每一次的溢出時間。

    糊塗窗口綜合症

    TCP的窗口協議,會引發一種一般叫作糊塗窗口綜合症的問題,具體表現爲,當客戶端通告一個小的非零窗口時,服務器馬上發送小數據給客戶端並充滿其緩衝區,一來二去就會讓網絡中充滿小TCP數據報,從而影響網絡利用率。對於發送方和接收端的這種糊塗行爲。TCP給出了一些建議(或者是規定)。

    1. 接收方不通告小窗口。一般的算法是接收方不通告一個比當前窗口大的窗口(能夠爲0),
      除非窗口能夠增長一個報文段大小(也就是將要接收的MSS)或者能夠增長接收方緩存空間
      的一半,不論實際有多少。
    2. 發送方避免出現糊塗窗口綜合症的措施是隻有如下條件之一知足時才發送數據: ( a )
      以發送一個滿長度的報文段; ( b )能夠發送至少是接收方通告窗口大小一半的報文段; ( c )能夠
      發送任何數據而且不但願接收ACK(也就是說,咱們沒有還未被確認的數據)或者該鏈接上
      不能使用Nagle算法。

    ok,如今咱們回憶一下,能夠發現TCP的不少規定都是爲了在一次傳送中發送儘可能多的數據,例如捎帶ACK數據報文的策略,Nagle算法,重傳時發送包含原數據報文的策略,等等。

    2.保活定時器

    保活定時器更加的簡單,還記得FTP或者Http服務器都有Sesstion Time機制麼?由於TCP是面向鏈接的,因此就會出現只鏈接不傳送數據的半開放鏈接,服務器固然要檢測到這種鏈接而且在某些狀況下釋放這種鏈接,這就是保活定時器的做用。其時限根據服務器的實現不一樣而不通。另外要提到的是,當其中一端若是崩潰並從新啓動的狀況下,若是收到該端前生的保活探察,則要發送一個RST數據報文幫助另外一端結束鏈接。

     


  • 轉載於 http://blog.csdn.net/goodboy1881

相關文章
相關標籤/搜索