你也許聽說過TCP/IP協議,那麼你知道到底什麼是TCP,什麼是IP嗎?在這一章裡面,我們一起來學習這個目前網絡上用最廣泛的協議.
7.1 網絡傳輸分層
如果你考過計算機等級考試,那麼你就應該已經知道了網絡傳輸分層這個概念.在網絡上,人們為了傳輸數據時的方便,把網絡的傳輸分為7個層次.分別是:應用層,表示層,會話層,傳輸層,網絡層,數據鏈路層和物理層.分好了層以後,傳輸數據時,上一層如果要數據的話,就可以直接向下一層要了,而不必要管數據傳輸的細節.下一層也只向它的上一層提供數據,而不要去管其它東西了.如果你不想考試,你沒有必要去記這些東西的.只要知道是分層的,而且各層的作用不同.
7.2 IP協議
IP協議是在網絡層的協議.它主要完成數據包的發送作用. 下面這個表是IP4的數據包格式
0 4 8 16 32
--------------------------------------------------
|版本 |首部長度|服務類型| 數據包總長 |
--------------------------------------------------
| 標識 |DF |MF| 碎片偏移 |
--------------------------------------------------
| 生存時間 | 協議 | 首部較驗和 |
------------------------------------------------
| 源IP地址 |
------------------------------------------------
| 目的IP地址 |
-------------------------------------------------
| 選項 |
=================================================
| 數據 |
-------------------------------------------------
下面我們看一看IP的結構定義
struct ip
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
unsigned int ip_hl:4; /* header length */
unsigned int ip_v:4; /* version */
#endif
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int ip_v:4; /* version */
unsigned int ip_hl:4; /* header length */
#endif
u_int8_t ip_tos; /* type of service */
u_short ip_len; /* total length */
u_short ip_id; /* identification */
u_short ip_off; /* fragment offset field */
#define IP_RF 0x8000 /* reserved fragment flag */
#define IP_DF 0x4000 /* dont fragment flag */
#define IP_MF 0x2000 /* more fragments flag */
#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */
u_int8_t ip_ttl; /* time to live */
u_int8_t ip_p; /* protocol */
u_short ip_sum; /* checksum */
struct in_addr ip_src, ip_dst; /* source and dest address */
};
ip_vIP協議的版本號,這裡是4,現在IPV6已經出來了
ip_hlIP包首部長度,這個值以4字節為單位.IP協議首部的固定長度為20個字節,如果IP包沒有選項,那麼這個值為5.
ip_tos服務類型,說明提供的優先權.
ip_len說明IP數據的長度.以字節為單位.
ip_id標識這個IP數據包.
ip_off碎片偏移,這和上面ID一起用來重組碎片的.
ip_ttl生存時間.沒經過一個路由的時候減一,直到為0時被拋棄.
ip_p協議,表示創建這個IP數據包的高層協議.如TCP,UDP協議.
ip_sum首部校驗和,提供對首部數據的校驗.
ip_src,ip_dst發送者和接收者的IP地址
關於IP協議的詳細情況,請參考 RFC791
7.3 ICMP協議
ICMP是消息控制協議,也處於網絡層.在網絡上傳遞IP數據包時,如果發生了錯誤,那麼就會用ICMP協議來報告錯誤.
ICMP包的結構如下:
0 8 16 32
---------------------------------------------------------------------
| 類型 | 代碼 | 校驗和 |
--------------------------------------------------------------------
| 數據 | 數據 |
--------------------------------------------------------------------
ICMP在中的定義是
struct icmphdr
{
u_int8_t type; /* message type */
u_int8_t code; /* type sub-code */
u_int16_t checksum;
union
{
struct
{
u_int16_t id;
u_int16_t sequence;
} echo; /* echo datagram */
u_int32_t gateway; /* gateway address */
struct
{
u_int16_t __unused;
u_int16_t mtu;
} frag; /* path mtu discovery */
} un;
};
關於ICMP協議的詳細情況可以查看 RFC792
7.4 UDP協議
UDP協議是建立在IP協議基礎之上的,用在傳輸層的協議.UDP和IP協議一樣是不可靠的數據報服務.UDP的頭格式為:
0 16 32
---------------------------------------------------
| UDP源端口 | UDP目的端口 |
---------------------------------------------------
| UDP數據報長度 | UDP數據報校驗 |
---------------------------------------------------
UDP結構在中的定義為:
struct udphdr {
u_int16_t source;
u_int16_t dest;
u_int16_t len;
u_int16_t check;
};
關於UDP協議的詳細情況,請參考 RFC768
7.5 TCP
TCP協議也是建立在IP協議之上的,不過TCP協議是可靠的.按照順序發送的.TCP的數據結構比前面的結構都要複雜.
0 4 8 10 16 24 32
-------------------------------------------------------------------
| 源端口 | 目的端口 |
-------------------------------------------------------------------
| 序列號 |
------------------------------------------------------------------
| 確認號 |
------------------------------------------------------------------
| | |U|A|P|S|F| |
|首部長度| 保留 |R|C|S|Y|I| 窗口 |
| | |G|K|H|N|N| |
-----------------------------------------------------------------
| 校驗和 | 緊急指針 |
-----------------------------------------------------------------
| 選項 | 填充字節 |
-----------------------------------------------------------------
TCP的結構在中定義為:
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1:4;
u_int16_t doff:4;
u_int16_t fin:1;
u_int16_t syn:1;
u_int16_t rst:1;
u_int16_t psh:1;
u_int16_t ack:1;
u_int16_t urg:1;
u_int16_t res2:2;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int16_t doff:4;
u_int16_t res1:4;
u_int16_t res2:2;
u_int16_t urg:1;
u_int16_t ack:1;
u_int16_t psh:1;
u_int16_t rst:1;
u_int16_t syn:1;
u_int16_t fin:1;
#endif
u_int16_t window;
u_int16_t check;
u_int16_t urg_prt;
};
source發送TCP數據的源端口
dest接受TCP數據的目的端口
seq標識該TCP所包含的數據字節的開始序列號
ack_seq確認序列號,表示接受方下一次接受的數據序列號.
doff數據首部長度.和IP協議一樣,以4字節為單位.一般的時候為5
urg如果設置緊急數據指針,則該位為1
ack如果確認號正確,那麼為1
psh如果設置為1,那麼接收方收到數據後,立即交給上一層程序
rst為1的時候,表示請求重新連接
syn為1的時候,表示請求建立連接
fin為1的時候,表示親戚關閉連接
window窗口,告訴接收者可以接收的大小
check對TCP數據進行較核
urg_ptr如果urg=1,那麼指出緊急數據對於歷史數據開始的序列號的偏移值
關於TCP協議的詳細情況,請查看 RFC793