文章目錄
前兩天中興電話面試竟然問了網絡模型分層這個不疼不癢的題目,尷尬的是還記得tcp/ip模型是4層,但當時怎麼數都是5層(被謝希仁的5層模型洗腦了),看來還是得複習複習
tcp首部封裝了端口號,ip首部封裝了IP地址,以太網首部封裝了主機的物理mac地址。
以太網幀(Frame)格式
其中的源地址和目的地址是指網卡的硬件地址(也叫MAC地址),長度是48位,是在網卡出廠時固化的。用ifconfig命令看一下,“HWaddr00:15:F2:14:9E:3F”部分就是硬件地址。協議字段有三種值,分別對應IP、ARP、RARP。幀末尾是CRC校驗碼。
以太網幀中的數據長度規定最小46字節,最大1500字節,ARP和RARP數據包的長度不夠46字節,要在後面補填充位(padding)。最大值1500稱爲以太網的最大傳輸單元(MTU),不同的網絡類型有不同的MTU,如果一個數據包從以太網路由到撥號鏈路上,數據包長度大於撥號鏈路的MTU了,則需要對數據包進行分片(fragmentation)。ifconfig命令的輸出中也有“MTU:1500”。注意,MTU這個概念指數據幀中有效載荷的最大長度,不包括幀首部的長度。
ARP協議:用來識別主機ip地址和mac地址的映射
例子:現在,1希望向4發送hello。arp先工作,構造以太網幀(arp數據報)。
目的mac不知道,用6個FF(6個字節)填充,6字節。
填充源mac,6字節。
類型爲0806,2字節。
然後是空位8字節。
然後是6字節源mac,4字節源ip,6字節目的mac,4字節目的ip。
構造好之後發送。
現在交換機上相連的主機都得到了這個以太網幀。
只有目的mac是自己主機的mac,或者是6個FF時,這些主機纔會接收;否則直接丟棄。
如果目的mac是6個FF,接受之後這些主機會查看目的ip,只有主機4的目的ip能對應上,它需要回應主機1一個包,把源mac設置爲自己的mac,而且主機1的mac已經獲得了,所以這個迴應的以太網幀只有主機1接收。
綜上,arp協議就是通過ip地址來獲得mac地址。
之後arp就不再用了,兩個主機之間靠mac地址通信。
網絡層數據包(Packet,也叫分組)格式
ip協議
ip在網絡層,解決的主要問題還是數據要送到哪個主機上。
ipv4地址佔4個字節。
下面看ip分組:
- ip首部佔20個字節:
- 4位版本,描述是ipv4還是ipv6
- 4位首部長度,首部默認是20個字節,如果有選項,首部會變長(還是4字節的倍數)
- 8位服務類型,用來獲得更好的服務.這個字段在舊標準中叫做服務類型,但實際上一直沒有被使用過.1998年IETF把這個字段改名爲區分服務 DS(Differentiated Services).只有在使用區分服務時,這個字段才起作用.
- 16位總長度,總長度指首都及數據之和的長度,單位爲字節.因爲總長度字段爲 16位,所以ip分組的最大長度爲 2^16-1=65 535字節。在IP層下面的每一種數據鏈路層都有自己的幀格式,其中包括幀格式中的數據字段的最大長度,即最大傳送單元 MTU (Maximum Transfer Unit)。當一個ip分組封裝成鏈路層的幀時,此ip分組的總長度 (即首部加上數據部分)一定不能超過下面的數據鏈路層的MTU值,否則要分片。
- 16位標識,IP軟件在存儲器中維持一個計數器,每產生一個ip分組,計數器就加 1,並將此值賦給標識字段.但這個"標識"並不是序號,因爲 IP是無連接的服務,ip分組不存在按序接收的問題.當ip分組由於長度超過網絡的 MTU 而必須分片時,這個標識字段的值就被複制到所有的ip分組的標識字段中.相同的標識字段的值使分片後的各ip分組的分片最後能正確地重裝成爲原來的ip分組.
- 3位標誌,但目前只有2位有意義. 標誌字段中的最低位記爲 MF(More Fragment).MF=1即表示後面"還有分片"的ip分組.MF=0表示這已是若干ip分組的分片中的最後一個.標誌字段中間的一位記爲DF(Don’t Fragment),意思是"不能分片",只有當 DF=0時才允許分片.
- 13位偏移,較長的分組在分片後,某片在原分組中的相對位置.也就是說,相對用戶數據字段的起點,該片從何處開始.片偏移以 8個字節爲偏移單位,這就是說,每個分片的長度一定是 8字節(64位)的整數倍.
- 8位生存時間TTL(下一跳),生存時間字段常用的英文縮寫是TTL(Time To Live),其表明ip分組在網絡中的壽命.由發出ip分組的源點設置這個字段.其目的是防止無法交付的ip分組無限制地在因特網中兜圈子,因而白白消耗網絡資源.最初的設計是以秒作爲 TTL的單位.每經過一個路由器時,就把TTL減去ip分組在路由器消耗掉的一段時間.若ip分組在路由器消耗的時間小於 1 秒,就把TTL值減 1.當 TTL值爲 0時,就丟棄這個ip分組.
- 8位協議,協議字段指出此ip分組攜帶的數據是使用何種協議,以便使目的主機的IP層知道應將數據部分上交給哪個處理過程.
- 16位校驗和,這個字段只檢驗ip分組的首部,但不包括數據部分。這是因爲ip分組每經過一個路由器,都要重新計算一下首都檢驗和 (一些字段,如生存時間,標誌,片偏移等都可能發生變化),不檢驗數據部分可減少計算的工作量.
- 32位源ip地址。
- 32位目的ip地址。
例子:用戶向新浪服務器發送hello
ip分組首先到達路由器100.100.100.1,然後有一個選擇路徑的問題。路由器先拆包,路由器在網絡層工作,mac地址沒用,直接丟掉,TTL減1,然後看目的ip是誰,然後路由器查路由表選路(不展開討論),選擇A路由器,轉發需要以太網協議,所以還得加上源mac地址和目的mac地址,這時的源mac地址就是路由器自己的mac地址,目的mac地址就是路由器A的mac地址;ip這一層不動。
直到送到新浪服務器;TTL爲0時還沒到達,被最後一個路由器丟棄(不再轉發)。
傳輸層協議格式
UDP數據報(Datagram)格式
可以看到,UDP協議頭部8個字節:
- 16位源端口號
- 16位目的端口號
- 16位UDP長度
- 16位UDP校驗和
UDP協議非常簡單,最重要的就是端口號的概念,端口號最大是 2^16=65536
例子:
TCP數據段(Segment)格式
- 16位源端口號
- 16位目的端口號
- 32位序號
- 32位確認序號
- 4位首部長度,以4字節爲單位
- 保留6位
- URG
- ACK
- PSH
- RST
- SYN
- FIN
- 16位窗口大小
- 16位校驗和
- 16位緊急指針
nat映射和打洞
nat映射
內網訪問外網ip地址時,網關會做一個NAT映射,將內網ip映射成外網ip,同時依靠端口映射將外網的數據傳遞給內網的主機。
nat打洞
假設小明和小紅兩個內網ip通過qq進行視頻聊天。二者登錄qq時,qq客戶端向qq服務器發送數據,qq服務器記錄二者的公網ip和端口,此時小明和小紅如果要視頻聊天可以通過第三方服務器(qq服務器)進行中轉,但是數據多轉了一手就會造成不必要的延時和卡頓。所以希望小明和小紅的客戶端直接互相訪問。此時又有一個情況,如果內網沒有向外網進行數據請求時,他們各自的網關會攔截外部的訪問數據(防止攻擊),所以小明和小紅需要先從qq服務器獲得彼此的公網ip和端口,然後小明給小紅髮送一條信息,這條信息雖然被小紅丟棄了,但是在這之後小紅給小明發送的數據小明都能接收到;同理,小紅給小明先發送一條數據,這條數據被丟棄,然後小明給小紅的數據小紅都能接收到。這個技術叫nat打洞。qq服務器在這個建立連接過程中扮演了一個提供公網ip和端口的角色,所以第三方服務器是必要的。
此外,如果小紅和小明的公網ip相同,證明他們在同一內網,就不需要打洞技術了。小明和小紅可以告知彼此的內網ip進行數據傳輸。
socket編程
服務器最小代碼實現
TCP IP協議棧都是在內核態實現的,協議棧什麼都有,socket就相當於協議棧實例化的一個對象,因爲socket指定了以太網協議,ipv4/ipv6,tcp/udp等。
cs模型: