mac/ip/TCP/udp报文格式与理论大小

发布日期:2013-04-13 13:53:16
乙太網路的 MAC 訊框
前导码(8bytes)|目的位址(6bytes)|来源位址(6bytes)|资料栏位通讯(2bytes)|主要资料(46-1500bytes)|检查码(4bytes)
圖三、乙太網路的 MAC 訊框 
在 這個 MAC 當中,最重要的就是那個 6 Bytes 的目的與來源位址了! 事實上,在所有的乙太網路卡當中都有一個獨一無二的網路卡卡號, 那就是上頭的『目的與來源位址』,這個位址是硬體位址( hardware address ), 共有 6 bytes ,分別由 00:00:00:00:00:00 到 FF:FF:FF:FF:FF:FF, 這 6 bytes 當中,前 3bytes 為廠商的代碼,後 3bytes 則是該廠商自行設定的裝置碼了。 在 Linux 當中,你可以使用 ifconfig 這個指令來查閱你的網路卡卡號喔! 不過,由於 MAC 主要是與網路卡卡號有關,所以我們也常常將 MAC 作為網路卡卡號的代稱。 特別注意,在這個 MAC 的傳送中,他僅在區域網路內生效, 如果跨過不同的網域 (這個後面 IP 的部分時會介紹),那麼來源與目的的位址就會跟著改變了。 這是因為變成不同網路卡之間的交流了嘛!所以卡號當然不同了!如下所示: 

在不同主機間持續傳送相同資料 
圖四、在不同主機間持續傳送相同資料的 MAC 訊框變化 
例 如上面的圖示,我的資料要由電腦 A 通過 B 後才送達 C ,而 B 電腦有兩塊網路卡, 其中 MAC-2 與 A 電腦的 MAC-1 互通,至於 MAC-3 則與 C 電腦的 MAC-4 互通。 但是 MAC-1 不能與 MAC-3 與 MAC-4 互通,為啥?因為 MAC-1 這塊網路卡並沒有與 MAC-3 及 MAC-4 使用同樣的 switch/hub 相接嘛!所以,資料的流通會變成: 
  1. 先由 MAC-1 傳送到 MAC-2 ,此時來源是 MAC-1 而目的地是 MAC-2;
  2. B 電腦接收後,察看該訊框,發現目標其實是 C 電腦,而為了與 C 電腦溝通, 所以他會將訊框內的來源 MAC 改為 MAC-3 ,而目的改為 MAC-4 ,如此就可以直接傳送到 C 電腦了。
也就是說,只要透過 B (就是路由器) 才將封包送到另一個網域 (IP 部分會講) 去的時候, 那麼訊框內的硬體位址就會被改變,然後才能夠在同一個網域裡面直接進行 frame 的流通啊! 
MAC包大小:旧为1900bytes,大为9000bytes
IP 封包的表頭
現 在我們知道 IP 這個資料封包 (packet) 是需要放置在 MAC 訊框裡面的,所以當然不能比 MAC 所能容許的最大資料量還大!但是 IP 封包其實可以到 65535 bytes 那麼大的吶! 那麼 IP 封包除了資料之外,他的表頭資料 (head) 是長怎樣呢? 在 圖三的 MAC 訊框表頭裡面最重要的莫過於那個網路卡硬體位址, 那麼在 IP 表頭裡面當然就以來源與目標的 IP 位址為最重要囉! 除此之外, IP 表頭裡面還含有哪些重要資料呢?如底下所示:(下圖第一行為每個欄位的bit 數) 

4 bits 4 bits 8 bits 3 bits 13 bits
Version IHL Type of Service Total Length
Identification Flags Fragmentation Offset
Time To Live Protocol Header Checksum
Source Address
Destination Address
Options Padding
Data
圖八、IP 封包的表頭資料 
在上面的圖示中有個地方要注意,那就是『 每一行所佔用的位元數為 32 bits』, 也就是說, IP 封包的表頭資料是 32 bits 的倍數喔!那各個表頭的內容分別介紹如下:
  • Version(版本)
    宣告這個 IP 封包的版本,例如目前慣用的還是 IPv4 這個版本,在這裡宣告的。

  • IHL(Internet Header Length, IP表頭的長度)
    告知這個 IP 封包的表頭長度,單位為位元組(bytes)。 此 IHL 長度的範圍為 5~15。

  • Type of Service(服務類型)
    這個項目的內容為『PPPDTRUU』,表示這個 IP 封包的服務類型,主要分為:
    PPP:表示此 IP 封包的優先度; D:若為 0 表示一般延遲(delay),若為 1 表示為低延遲;
    T:若為 0 表示為一般傳輸量 (throughput),若為 1 表示為高傳輸量;
    R:若為 0 表示為一般可靠度(reliability),若為 1 表示高可靠度。
    UU:保留尚未被使用。
    我們前面談到 gigabit 乙太網路時曾提到 Jumbo frame 對吧!可以提高 MTU, 由於 gigabit 乙太網路的種種相關規格可以讓這個 IP 封包加速且降低延遲, 某些特殊的標誌就是在這裡說明的。

  • Total Length(總長度)
    指這個 IP 封包的總容量,包括表頭與內容 (Data) 部分。最大可達 65535 bytes。

  • Identification(辨別碼)
    我 們前面提到 IP 袋子必須要放在 MAC 袋子當中。不過,如果 IP 袋子太大的話, 就得先要將 IP 再重組成較小的袋子然後再放到 MAC 當中。而當 IP 被重組時, 每個來自同一筆資料的小 IP 就得要有個識別碼以告知接收端這些小 IP 其實是來自同一個封包才行。 也就是說,假如 IP 封包其實是 65536 那麼大 (前一個 Total Length 有規定), 那麼這個 IP 就得要再被分成更小的 IP 分段後才能塞進 MAC 訊框中。那麼每個小 IP 分段是否來自同一個 IP 資料,呵呵!這裡就是那個識別碼啦!

  • Flags(特殊旗標)
    這個地方的內容為『0DM』,其意義為:
    D:若為 0 表示可以分段,若為 1 表示不可分段
    M:若為 0 表示此 IP 為最後分段,若為 1 表示非最後分段。

  • Fragment Offset(分段偏移)
    表 示目前這個 IP 分段在原始的 IP 封包中所佔的位置。 就有點像是序號啦,有這個序號才能將所有的小 IP 分段組合成為原本的 IP 封包大小嘛! 透過 Total Length, Identification, Flags 以及這個 Fragment Offset 就能夠將小 IP 分段在收受端組合起來囉!

  • Time To Live(TTL, 存活時間)
    表示這個 IP 封包的存活時間,範圍為 0-255。當這個 IP 封包通過一個路由器時, TTL 就會減一,當 TTL 為 0 時,這個封包將會被直接丟棄。說實在的,要讓 IP 封包通過 255 個路由器,還挺難的~ ^_^

  • Protocol Number(協定代碼)
    由於網路上面的封包協定太多了,每個協定都是裝在 IP 當中的, 所以 IP 當然就得在表頭上面告知收受端,這個 IP 內含有的資料是什麼協定才行。 一般常見的網路協定如下所示:
    IP 內的號碼 協定名稱(全名)
    1 ICMP (Internet Control Message Protocol)
    2 IGMP (Internet Group Management Protocol)
    3 GGP (Gateway-to-Gateway Protocol)
    4 IP (IP in IP encapsulation)
    6 TCP (Transmission Control Protocol)
    8 EGP (Exterior Gateway Protocol)
    17 UDP (User Datagram Protocol)
    當然啦,我們比較常見到的還是那個 TCP, UDP, ICMP 說!

  • Header Checksum(表頭檢查碼)
    用來檢查這個 IP 表頭的錯誤檢驗之用。

  • Source Address
    還用講嗎?當然是來源的 IP 位址,相關的 IP 我們之前提過囉!

  • Destination Address
    有來源還需要有目標才能傳送,這裡就是目標的 IP 位址。

  • Options (其他參數)
    這個是額外的功能,提供包括安全處理機制、路由紀錄、時間戳記、 嚴格與寬鬆之來源路由等。

  • Padding(補齊項目)
    由於 Options 的內容不一定有多大,但是我們知道 IP 每個資料都必須要是 32 bits, 所以,若 Options 的資料不足 32 bits 時,則由 padding 主動補齊。

你 只要知道 IP 表頭裡面還含有: TTL, Protocol, 來源 IP 與目標 IP 也就夠了! 而這個 IP 表頭的來源與目標 IP ,以及那個判斷通過多少路由器的 TTL ,就能瞭解到這個 IP 將被如何傳送到目的端吶。下一節我們將介紹一下那麼 IP 封包是如何被傳送到目的地?
TCP 協定
在前幾個小節內談到的 IP 與路由的相關說明中,我們知道 IP 與路由僅能將資料封包傳送到正確的目標而已, 但是這個目的地是否真的能夠收下來這個封包?那可就不一定了。要確認該資料能否正確的被目的端所接收, 就必須要在資料封包上面多加一些參數來判斷才行。 

在前面的 OSI 七層協定當中,在網路層的 IP 之上則是傳送層,而傳送層的資料打包成什麼? 最常見的就是 TCP 封包了。這個 TCP 封包資料必須要能夠放到 IP 的資料袋當中才行喔! 所以,我們可以將 MAC, IP 與 TCP 的封包資料這樣看: 
各封包之間的相關性 
圖十一、各封包之間的相關性 
所以說,IP 除了表頭之外的 Data 內容其實就是 TCP 封包的表頭與內容;而 MAC 的 Data 內容, 就是一個完整的 IP 封包資料!這也是我們上頭提到的,最終還是得以 MAC 能夠支援的最大容許容量, 才能夠決定 IP 與 TCP 封包是否需要再進行分段的工作。那麼既然 MAC 與 IP 都有表頭資料, 想當然爾,TCP 也有表頭資料來記錄該封包的相關資訊囉??沒錯啦~ TCP 封包的表頭是長這個樣子的: 

4 bits 6 bits 6 bits 8 bits 8 bits
Source Port Destination Port
Sequence Number
Acknowledge Number
Data
Offset
Reserved Code Window
Ckecksum Urgent Pointer
Options Padding
Data
圖十二、TCP 封包的表頭資料 
上圖就是一個 TCP 封包的表頭資料,各個項目以 Source Port, Destination Port 及 Code 算是比較重要的項目,底下我們就分別來談一談各個表頭資料的內容吧! 
  • Source Port & Destination Port ( 來源埠口 & 目標埠口 )
    什 麼是埠口(port)?我們知道 IP 封包的傳送主要是藉由 IP 位址連接兩端, 但是到底這個連線的通道是連接到哪裡去呢?沒錯!就是連接到 port 上頭啦! 舉例來說,鳥站 (http://linux.vbird.org) 有開放 WWW 伺服器, 這表示鳥站的主機必須要啟動一個可以讓 client 端連接的端口,這個端口就是 port , 中文翻譯成為埠口。同樣的,用戶端想要連接到鳥哥的鳥站時,就必須要在 client 主機上面啟動一個 port ,這樣這兩個主機才能夠利用這條『通道』來傳遞封包資料喔! 這個目標與來源 port 的紀錄,可以說是 TCP 封包上最重要的參數了! 下個小單元我們還會繼續介紹。

  • Sequence Number ( 封包序號 )
    由於 TCP 封包必須要帶入 IP 封包當中,所以如果 TCP 資料太大時(大於 IP 封包的容許程度), 就得要進行分段。這個 Sequence Number 就是記錄每個封包的序號, 可以讓收受端重新將 TCP 的資料組合起來。

  • Acknowledge Number ( 回應序號 ) 
    為 了確認主機端確實有收到我們 client 端所送出的封包資料,我們 client 端當然希望能夠收到主機方面的回應,那就是這個 Acknowledge Number 的用途了。 當 client 端收到這個確認碼時,就能夠確定之前傳遞的封包已經被正確的收下了。 

  • Data Offset (資料補償)
    在圖十二倒數第二行有個 Options 欄位對吧!那個 Options 的欄位長度是非固定的, 而為了要確認整個 TCP 封包的大小,就需要這個標誌來說明整個封包區段的起始位置。 

  • Reserved (保留)
    未使用的保留欄位。

  • Code (Control Flag, 控制標誌碼)
    當我們在進行網路連線的時候,必須要說明這個連線的狀態,好讓接收端瞭解這個封包的主要動作。 這可是一個非常重要的控制碼喔!這個欄位共有 6 個 bits ,分別代表 6 個控制碼,若為 1 則為啟動。分別說明如下:

    • URG(Urgent):若為 1 則代表該封包為緊急封包, 接收端應該要緊急處理,且圖十二當中的 Urgent Pointer 欄位也會被啟用。

    • ACK(Acknowledge):若為 1 代表這個封包為回應封包, 則與上面提到的 Acknowledge Number 有關。

    • PSH(Push function):若為 1 時, 代表要求對方立即傳送緩衝區內的其他對應封包,而無須等待緩衝區滿了才送。

    • RST(Reset):如果 RST 為 1 的時候, 表示連線會被馬上結束,而無需等待終止確認手續。這也就是說,這是個強制結束的連線, 且發送端已斷線。

    • SYN(Synchronous):若為 1 , 表示發送端希望雙方建立同步處理,也就是要求建立連線。通常帶有 SYN 標誌的封包表示『主動』要連接到對方的意思。

    • FIN(Finish):若為 1 ,表示傳送結束, 所以通知對方資料傳畢,是否同意斷線,只是發送者還在等待對方的回應而已。

    其中比較常見到的應該是 ACK/SYN/FIN 等,這三個控制碼是務必要記下來的, 這樣未來在談到防火牆的時候,您才會比較清楚為啥每個 TCP 封包都有所謂的『狀態』條件! 那就是因為連線方向的不同所致啊!底下我們會進一步討論喔! 

  • Window (滑動視窗)
    主要是用來控制封包的流量的,可以告知對方目前本身有的緩衝器容量(Receive Buffer) 還可以接收封包。當 Window=0 時,代表緩衝器已經額滿,所以應該要暫停傳輸資料。 Window 的單位是 byte。

  • Checksum(確認檢查碼)
    當 資料要由發送端送出前,會進行一個檢驗的動作,並將該動作的檢驗值標注在這個欄位上; 而接收者收到這個封包之後,會再次的對封包進行驗證,並且比對原發送的 Checksum 值是否相符,如果相符就接受,若不符就會假設該封包已經損毀,進而要求對方重新發送此封包! 

  • Urgent Pointer(緊急資料)
    這個欄位是在 Code 欄位內的 URG = 1 時才會產生作用。可以告知緊急資料所在的位置。 

  • Options(任意資料)
    目前此欄位僅應用於表示接收端可以接收的最大資料區段容量,若此欄位不使用, 表示可以使用任意資料區段的大小。這個欄位較少使用。 

  • Padding(補足欄位)
    如同 IP 封包需要有固定的 32bits 表頭一樣, Options 由於欄位為非固定, 所以也需要 Padding 欄位來加以補齊才行。同樣也是 32 bits 的整數。

 

TCP报文格式

 — TCP :( Transmission Control Protocol)     面向连接的可靠传输协议,为用户应用端之间提供一个虚拟电路。

— 源端口(Source Port):呼叫端端口号

— 目端口(Destination Port):被叫端端口号

— 序列号(Sequence Number):分配给报文的序号,用于跟踪报文通信顺序,确保无丢失

— 确认号(Acknowledgement Number):所期待的下一个TCP报文的序列号,并表示

                   对此序列前报文正确接收的确认

— 报头长度(HLEN):报文头部的字节数

— 保留域(Reserved):设置为0

— 编码位(Code Bits):控制功能(如TCP连接的建立和终止)

— 窗口(Window):发送者同意接收的字节数

— 校验和(Checksum):报头和数据字段的校验和

— 紧急指针(Urgent Pointer):指示紧急数据段的末尾

— 选项(Option):当前定义TCP段的最大值

— 数据(Data):上层协议数据

   TCP连接的建立实际上是一同步过程(又称三次握手)   

 三次握手:

     1:主机A向主机B发出连接请求数据包

     2:主机B向主机A发送同意连结和要求同步(一个在发送,一个在接收)

     3:主机A要发出一数据包确认主机B的要求同步

 

 

 

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山源端口和目的端口:发送方和接收方的TCP端口号。

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山序号:该报文数据在发送方的数据流中的位置。当前时间值计算出一个数值作为起始序号。

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山首部长度:表示TCP报文首部信息的长度。由于首部可能含有选项内容,因此TCP首部的长度是不确定的。首部长度的单位是32位或4字节。首部长度实际上也指示了数据区在报文段中的起始偏移值。

 

码元比特:6位

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山URG、ACK、PSH、RST、SYN、FIN。

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山URG表示紧急指针字段有效;

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山ACK置位表示确认号字段有效;

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山PSH表示当前报文需要请求推(push)操作;

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山RST置位表示复位TCP连接;

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山SYN用于建立TCP连接时同步序号;

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山FIN用于释放TCP连接时标识发送方比特流结束

 

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山窗口:窗口通告值。发送方根据接收的窗口通告值调整窗口大小。

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山紧急指针:如果TCP通信中,一方有紧急的数据(例如中断或退出命令)需要尽快发送给接收方,并且让接收方的TCP协议尽快通知相应的应用程序,可以将URG置位,并通过紧急指针指示紧急数据在报文段中的结束位置。

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山校验和:与UDP校验和计算方法相同,同样需要包含伪首部。伪首部中的协议类型值为6。

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山选项:用于TCP连接双方在建立连接时协商最大的报文段长度MSS(Maximum Segment Size)。

TCP报文格式/udp报文格式 - 江山笑 - 我的江山,大家的江山填充:为了使选项字段对齐32比特,可能采用若干位0作为填充数据。

 

 

UDP报文格式

 — UDP :( User Datagram Protocol)无连接的非可靠传输协议

— 源端口(Source Port):呼叫端端口号

— 目端口(Destination Port):被叫端端口号

— 报头长度(HLEN):报文头部的字节数

— 校验和(Checksum):报头和数据字段的校验和

— 数据(Data):上层协议数据

UDP 传输不提供ACK反向确认机制、流量和报文序列号控制,因此UDP报文可能会丢失、重复或无序到达,通信的可靠性问题将由应用层协议提供保障。但UDP报 文格式和控制机制简单,因此通信开销比较小,TFTP、SNMP、NFS和DNS应用层协议等都是用UDP传输的。

 

传输层: 
对于UDP协议来说,整个包的最大长度为65535,其中包头长度是65535-20=65515; 
对于TCP协议来说,整个包的最大长度是由最大传输大小(MSS,Maxitum Segment Size)决定,MSS就是TCP数据包每次能够传 
输的最大数据分段。为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需 
要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值 
确定为这次连接的最大MSS值。

IP层:

对于IP协议来说,IP包的大小由MTU决定(IP数据包长度就是MTU-28(包头长度)。 MTU值越大,封包就越大,理论上可增加传送速率,但 
MTU值又不能设得太大,因为封包太大,传送时出现错误的机会大增。一般默认的设置,PPPoE连接的最高MTU值是1492, 而以太网 
(Ethernet)的最高MTU值则是1500,而在Internet上,默认的MTU大小是576字节

 

 

UDP一次发送数据包的大小,TCP一次发送数据包的大小。

MTU最大传输单元,这个最大传输单元实际上和链路层协议有着密切的关系,EthernetII帧的结构DMAC+SMAC+Type+Data+CRC由于以太网传输电气方面的限制,每个以太网帧都有最小的大小64bytes最大不能超过1518bytes,对于小于或者大于这个限制的以太网帧我们都可以视之为错误的数据帧,一般的以太网转发设备会丢弃这些数据帧。

由 于以太网EthernetII最大的数据帧是1518Bytes这样,刨去以太网帧的帧头(DMAC目的MAC地址48bit=6Bytes+SMAC源 MAC地址48bit=6Bytes+Type域2bytes)14Bytes和帧尾CRC校验部分4Bytes那么剩下承载上层协议的地方也就是Data域最大就只能有1500Bytes这个值我们就把它称之为MTU。

PPPoE所谓PPPoE就是在以太网上面跑PPP协议,有人奇怪了,PPP协议和Ethernet不都是链路层协议吗?怎么一个链路层跑到另外一个链路层上面去了,难道升级成网络层协议了不成。其实这是个误区:就是某层协议只能承载更上一层协议。

为什么会产生这种奇怪的需求呢?这是因为随着宽带接入(这种宽带接入一般为Cable Modem或者xDSL或者以太网的接入),因为以太网缺乏认证计费机制而传统运营商是通过PPP协议来对拨号等接入服务进行认证计费的.

PPPoE带来了好处,也带来了一些坏处,比如:二次封装耗费资源,降低了传输效能等等,这些坏处俺也不多说了,最大的坏处就是PPPoE导致MTU变小了以太网的MTU是1500,再减去PPP的包头包尾的开销(8Bytes),就变成1492。

UDP 包的大小就应该是 1492 - IP头(20) - UDP头(8) = 1464(BYTES)

TCP 包的大小就应该是 1492 - IP头(20) - TCP头(20) = 1452(BYTES)

目前大多数的路由设备的MTU都为1500

编程的时候一定要注意哦,不能超过这两个值,否则你的传输效率就大打折扣了。