tcp/ip 傳輸的整個過程
阿新 • • 發佈:2019-02-08
假設某主機上的網路介面配置和路由表如下: $ ifconfig
eth0 Link encap:Ethernet HWaddr 00:0C:29:C2:8D:7E
inet addr:192.168.10.223 Bcast:192.168.10.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:0 (0.0 b) TX bytes:420 (420.0 b)
Interrupt:10 Base address:0x10a0 eth1 Link encap:Ethernet HWaddr 00:0C:29:C2:8D:88
inet addr:192.168.56.136 Bcast:192.168.56.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:603 errors:0 dropped:0 overruns:0 frame:0
TX packets:110 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:55551 (54.2 Kb) TX bytes:7601 (7.4 Kb)
Interrupt:9 Base address:0x10c0 lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:37 errors:0 dropped:0 overruns:0 frame:0
TX packets:37 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3020 (2.9 Kb) TX bytes:3020 (2.9 Kb)
$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.10.0 * 255.255.255.0 U 0 0 0 eth0
192.168.56.0 * 255.255.255.0 U 0 0 0 eth1
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default 192.168.10.1 0.0.0.0 UG 0 0 0 eth0 這臺主機有兩個網路介面,一個網路介面連到192.168.10.0/24網路,另一個網路介面連到192.168.56.0/24網路。路由表的Destination是目的網路地址,Genmask是子網掩碼,Gateway是下一跳地址,Iface是傳送介面,Flags中的U標誌表示此條目有效(可以禁用某些條目),G標誌表示此條目的下一跳地址是某個路由器的地址,沒有G標誌的條目表示目的網路地址是與本機介面直接相連的網路,不必經路由器轉發,因此下一跳地址處記為*號。 如果要傳送的資料包的目的地址是192.168.56.3,跟第一行的子網掩碼做與運算得到192.168.56.0,與第一行的目的網路地址不符,再跟第二行的子網掩碼做與運算得到192.168.56.0,正是第二行的目的網路地址,因此從eth1介面傳送出去,由於192.168.56.0/24正是與eth1介面直接相連的網路,因此可以直接發到目的主機,不需要經路由器轉發。 如果要傳送的資料包的目的地址是202.10.1.2,跟前三行路由表條目都不匹配,那麼就要按預設路由條目,從eth0介面發出去,首先發往192.168.10.1路由器,再讓路由器根據它的路由表決定下一跳地址。 6. UDP段格式 下圖是UDP的段格式(該圖出自[TCPIP])。 圖 36.11. UDP段格式
下面分析一幀基於UDP的TFTP協議幀。
乙太網首部
0000: 00 05 5d 67 d0 b1 00 05 5d 61 58 a8 08 00
IP首部
0000: 45 00
0010: 00 53 93 25 00 00 80 11 25 ec c0 a8 00 37 c0 a8
0020: 00 01
UDP首部
0020: 05 d4 00 45 00 3f ac 40
TFTP協議
0020: 00 01 ‘c”:”\”q’
0030: ‘w”e”r”q”.”q”w”e’00 ‘n”e”t”a’’s”c”i’
0040: ‘i’00 ‘b”l”k’’s”i”z”e’00 ‘5”1”2′00 ‘t”i’
0050: ‘m”e”o”u”t’00 ‘1”0′00 ‘t’’s”i”z”e’00 ‘0′
0060: 00 乙太網首部:源MAC地址是00:05:5d:61:58:a8,目的MAC地址是00:05:5d:67:d0:b1,上層協議型別0×0800表示IP。 IP首部:每一個位元組0×45包含4位版本號和4位首部長度,版本號為4,即IPv4,首部長度為5,說明IP首部不帶有選項欄位。服務型別為0,沒有使用服務。16位總長度欄位(包括IP首部和IP層payload的長度)為0×0053,即83位元組,加上乙太網首部14位元組可知整個幀長度是97位元組。IP報標識是0×9325,標誌欄位和片偏移欄位設定為0×0000,就是DF=0允許分片,MF=0此資料報沒有更多分片,沒有分片偏移。TTL是0×80,也就是128。上層協議0×11表示UDP協議。IP首部校驗和為0×25ec,源主機IP是c0 a8 00 37(192.168.0.55),目的主機IP是c0 a8 00 01(192.168.0.1)。 UDP首部:源埠號0×05d4(1492)是客戶端的埠號,目的埠號0×0045(69)是TFTP服務的well-known埠號。UDP報長度為0×003f,即63位元組,包括UDP首部和UDP層payload的長度。UDP首部和UDP層payload的校驗和為0xac40。 TFTP是基於文字的協議,各欄位之間用位元組0分隔,開頭的00 01表示請求讀取一個檔案,接下來的各欄位是: c:\qwerq.qwe
netascii
blksize 512
timeout 10
tsize 0 一般的網路通訊都是像TFTP協議這樣,通訊的雙方分別是客戶端和伺服器,客戶端主動發起請求(上面的例子就是客戶端發起的請求幀),而伺服器被動地等待、接收和應答請求。客戶端的IP地址和埠號唯一標識了該主機上的TFTP客戶端程序,伺服器的IP地址和埠號唯一標識了該主機上的TFTP服務程序,由於客戶端是主動發起請求的一方,它必須知道伺服器的IP地址和TFTP服務程序的埠號,所以,一些常見的網路協議有預設的伺服器埠,例如HTTP服務預設TCP協議的80埠,FTP服務預設TCP協議的21埠,TFTP服務預設UDP協議的69埠(如上例所示)。在使用客戶端程式時,必須指定伺服器的主機名或IP地址,如果不明確指定埠號則採用預設埠,請讀者查閱ftp、tftp等程式的man page瞭解如何指定埠號。/etc/services中列出了所有well-known的服務埠和對應的傳輸層協議,這是由IANA(Internet Assigned Numbers Authority)規定的,其中有些服務既可以用TCP也可以用UDP,為了清晰,IANA規定這樣的服務採用相同的TCP或UDP預設埠號,而另外一些TCP和UDP的相同埠號卻對應不同的服務。 很多服務有well-known的埠號,然而客戶端程式的埠號卻不必是well-known的,往往是每次執行客戶端程式時由系統自動分配一個空閒的埠號,用完就釋放掉,稱為ephemeral的埠號,想想這是為什麼。 前面提過,UDP協議不面向連線,也不保證傳輸的可靠性,例如: 傳送端的UDP協議層只管把應用層傳來的資料封裝成段交給IP協議層就算完成任務了,如果因為網路故障該段無法發到對方,UDP協議層也不會給應用層返回任何錯誤資訊。 接收端的UDP協議層只管把收到的資料根據埠號交給相應的應用程式就算完成任務了,如果傳送端發來多個數據包並且在網路上經過不同的路由,到達接收端時順序已經錯亂了,UDP協議層也不保證按傳送時的順序交給應用層。 通常接收端的UDP協議層將收到的資料放在一個固定大小的緩衝區中等待應用程式來提取和處理,如果應用程式提取和處理的速度很慢,而傳送端傳送的速度很快,就會丟失資料包,UDP協議層並不報告這種錯誤。 因此,使用UDP協議的應用程式必須考慮到這些可能的問題並實現適當的解決方案,例如等待應答、超時重發、為資料包編號、流量控制等。一般使用UDP協議的應用程式實現都比較簡單,只是傳送一些對可靠性要求不高的訊息,而不傳送大量的資料。例如,基於UDP的TFTP協議一般只用於傳送小檔案(所以才叫trivial的ftp),而基於TCP的FTP協議適用於各種檔案的傳輸。下面看TCP協議如何用面向連線的服務來代替應用程式解決傳輸的可靠性問題。 7. TCP協議
eth0 Link encap:Ethernet HWaddr 00:0C:29:C2:8D:7E
inet addr:192.168.10.223 Bcast:192.168.10.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:0 (0.0 b) TX bytes:420 (420.0 b)
Interrupt:10 Base address:0x10a0 eth1 Link encap:Ethernet HWaddr 00:0C:29:C2:8D:88
inet addr:192.168.56.136 Bcast:192.168.56.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:603 errors:0 dropped:0 overruns:0 frame:0
TX packets:110 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:100
RX bytes:55551 (54.2 Kb) TX bytes:7601 (7.4 Kb)
Interrupt:9 Base address:0x10c0 lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:37 errors:0 dropped:0 overruns:0 frame:0
TX packets:37 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3020 (2.9 Kb) TX bytes:3020 (2.9 Kb)
$ route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.10.0 * 255.255.255.0 U 0 0 0 eth0
192.168.56.0 * 255.255.255.0 U 0 0 0 eth1
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default 192.168.10.1 0.0.0.0 UG 0 0 0 eth0 這臺主機有兩個網路介面,一個網路介面連到192.168.10.0/24網路,另一個網路介面連到192.168.56.0/24網路。路由表的Destination是目的網路地址,Genmask是子網掩碼,Gateway是下一跳地址,Iface是傳送介面,Flags中的U標誌表示此條目有效(可以禁用某些條目),G標誌表示此條目的下一跳地址是某個路由器的地址,沒有G標誌的條目表示目的網路地址是與本機介面直接相連的網路,不必經路由器轉發,因此下一跳地址處記為*號。 如果要傳送的資料包的目的地址是192.168.56.3,跟第一行的子網掩碼做與運算得到192.168.56.0,與第一行的目的網路地址不符,再跟第二行的子網掩碼做與運算得到192.168.56.0,正是第二行的目的網路地址,因此從eth1介面傳送出去,由於192.168.56.0/24正是與eth1介面直接相連的網路,因此可以直接發到目的主機,不需要經路由器轉發。 如果要傳送的資料包的目的地址是202.10.1.2,跟前三行路由表條目都不匹配,那麼就要按預設路由條目,從eth0介面發出去,首先發往192.168.10.1路由器,再讓路由器根據它的路由表決定下一跳地址。 6. UDP段格式 下圖是UDP的段格式(該圖出自[TCPIP])。 圖 36.11. UDP段格式
0000: 00 05 5d 67 d0 b1 00 05 5d 61 58 a8 08 00
IP首部
0000: 45 00
0010: 00 53 93 25 00 00 80 11 25 ec c0 a8 00 37 c0 a8
0020: 00 01
UDP首部
0020: 05 d4 00 45 00 3f ac 40
TFTP協議
0020: 00 01 ‘c”:”\”q’
0030: ‘w”e”r”q”.”q”w”e’00 ‘n”e”t”a’’s”c”i’
0040: ‘i’00 ‘b”l”k’’s”i”z”e’00 ‘5”1”2′00 ‘t”i’
0050: ‘m”e”o”u”t’00 ‘1”0′00 ‘t’’s”i”z”e’00 ‘0′
0060: 00 乙太網首部:源MAC地址是00:05:5d:61:58:a8,目的MAC地址是00:05:5d:67:d0:b1,上層協議型別0×0800表示IP。 IP首部:每一個位元組0×45包含4位版本號和4位首部長度,版本號為4,即IPv4,首部長度為5,說明IP首部不帶有選項欄位。服務型別為0,沒有使用服務。16位總長度欄位(包括IP首部和IP層payload的長度)為0×0053,即83位元組,加上乙太網首部14位元組可知整個幀長度是97位元組。IP報標識是0×9325,標誌欄位和片偏移欄位設定為0×0000,就是DF=0允許分片,MF=0此資料報沒有更多分片,沒有分片偏移。TTL是0×80,也就是128。上層協議0×11表示UDP協議。IP首部校驗和為0×25ec,源主機IP是c0 a8 00 37(192.168.0.55),目的主機IP是c0 a8 00 01(192.168.0.1)。 UDP首部:源埠號0×05d4(1492)是客戶端的埠號,目的埠號0×0045(69)是TFTP服務的well-known埠號。UDP報長度為0×003f,即63位元組,包括UDP首部和UDP層payload的長度。UDP首部和UDP層payload的校驗和為0xac40。 TFTP是基於文字的協議,各欄位之間用位元組0分隔,開頭的00 01表示請求讀取一個檔案,接下來的各欄位是: c:\qwerq.qwe
netascii
blksize 512
timeout 10
tsize 0 一般的網路通訊都是像TFTP協議這樣,通訊的雙方分別是客戶端和伺服器,客戶端主動發起請求(上面的例子就是客戶端發起的請求幀),而伺服器被動地等待、接收和應答請求。客戶端的IP地址和埠號唯一標識了該主機上的TFTP客戶端程序,伺服器的IP地址和埠號唯一標識了該主機上的TFTP服務程序,由於客戶端是主動發起請求的一方,它必須知道伺服器的IP地址和TFTP服務程序的埠號,所以,一些常見的網路協議有預設的伺服器埠,例如HTTP服務預設TCP協議的80埠,FTP服務預設TCP協議的21埠,TFTP服務預設UDP協議的69埠(如上例所示)。在使用客戶端程式時,必須指定伺服器的主機名或IP地址,如果不明確指定埠號則採用預設埠,請讀者查閱ftp、tftp等程式的man page瞭解如何指定埠號。/etc/services中列出了所有well-known的服務埠和對應的傳輸層協議,這是由IANA(Internet Assigned Numbers Authority)規定的,其中有些服務既可以用TCP也可以用UDP,為了清晰,IANA規定這樣的服務採用相同的TCP或UDP預設埠號,而另外一些TCP和UDP的相同埠號卻對應不同的服務。 很多服務有well-known的埠號,然而客戶端程式的埠號卻不必是well-known的,往往是每次執行客戶端程式時由系統自動分配一個空閒的埠號,用完就釋放掉,稱為ephemeral的埠號,想想這是為什麼。 前面提過,UDP協議不面向連線,也不保證傳輸的可靠性,例如: 傳送端的UDP協議層只管把應用層傳來的資料封裝成段交給IP協議層就算完成任務了,如果因為網路故障該段無法發到對方,UDP協議層也不會給應用層返回任何錯誤資訊。 接收端的UDP協議層只管把收到的資料根據埠號交給相應的應用程式就算完成任務了,如果傳送端發來多個數據包並且在網路上經過不同的路由,到達接收端時順序已經錯亂了,UDP協議層也不保證按傳送時的順序交給應用層。 通常接收端的UDP協議層將收到的資料放在一個固定大小的緩衝區中等待應用程式來提取和處理,如果應用程式提取和處理的速度很慢,而傳送端傳送的速度很快,就會丟失資料包,UDP協議層並不報告這種錯誤。 因此,使用UDP協議的應用程式必須考慮到這些可能的問題並實現適當的解決方案,例如等待應答、超時重發、為資料包編號、流量控制等。一般使用UDP協議的應用程式實現都比較簡單,只是傳送一些對可靠性要求不高的訊息,而不傳送大量的資料。例如,基於UDP的TFTP協議一般只用於傳送小檔案(所以才叫trivial的ftp),而基於TCP的FTP協議適用於各種檔案的傳輸。下面看TCP協議如何用面向連線的服務來代替應用程式解決傳輸的可靠性問題。 7. TCP協議