设计人员为每个接入网络中的主机都分配一个 IP 地址(Internet Protocol Address),是一个 32 位的整数地址

只有合法的 IP 地址才能接入互联网中并且与其他主机进行通信

IP 地址是软件地址,不是硬件地址。
硬件 MAC 地址是存储在网卡中的,应用于本地网络中寻找目标主机。

网络地址转换(NAT)


它是一种把内部私有网络地址(IP 地址)翻译成合法网络 IP 地址的技术。

具有 NAT 功能的路由器必须拥有一个内部地址与一个外部地址。
内部地址:是为了与局域网的用户通信而使用的,它使用一个特定的内部 IP 地址,如 192.168.0.1(也是局域网的网关)。
外部地址:是与广域网进行通信而使用的,这是一个有效的 IP 地址,通常为运营商分配给我们。

IP报文

image.png

image.pngimage.pngimage.pngimage.png

IP首部片段 长度
/bit
解释
版本 4 IPv4,该值为 4;
对于 IPv6,该值为 6。
首部字段 4 用于记录 IP 首部的数据的长度
IP 首部中包含了一些可变的数据选项,故需要这 4bit 记录首部的长度
服务类型(TOS) 8 以便使不同类型的 IP 数据报(例如,一些特别要求低时延、高吞吐量或可靠性的数据报)能相互区别开来。
数据包长度 16 IP 数据报的总长度(首部+数据区域)
因为该字段长为 16bit,所以整个 IP 数据报的理论最大长度为 65535 字节
标识 16 用于表示 IP 层发送出去的每一份 IP 数据报,在发送每一份报文,该值加 1。
在分片的时候,该字段会被复制到每个分片数据报中,在目标接收主机中,使用该字段判断这些数据是否属于同一个 IP 数据报
标志 3 第一位保留未用;
第二位是不分片标志位,如果该位为 1,则表示 IP 数据报在发送的过程中不允许进行分片。(如果这个 IP 数据报的大小超过链路层能承载的大小,这个 IP 数据报将被丢弃,)
第三位:更多分片位,如果为 1 则表示该分片数据报不是整个 IP 数据报
的最后一个分片,如果为 0 则表示是整个 IP 数据报的最后一个分片。
分片偏移量 13 表示当前分片所携带的数据在整个 IP 数据报中的相对偏移位置(以 8 字节为单位),才能将分片进行重装为一个完整的 IP 数据报,并且重装 IP 数据报的依据就是分片的偏移量。
生存时间 8 该字段用来确保数据报不会永远在网络中循环。
每当 IP 数据报由一台路由器处理时,该字段的值减 1

若 TTL 字段减为 0,则该数据报必须丢弃,同时会返回一个 ICMP 差错报文给源主机,这样子数据就不会永远在网络中漂流而占据资源。
上层协议 8 该字段仅在一个 IP 数据报到达其最终目的地才会有用。
该字段的值指示了 IP 数据报的数据部分应交给哪个特定的传输层协议。
值为 6 表明数据部分要交给 TCP
值为 17 表明数据要交给 UDP


在 IP 数据报中的协议号所起的作用,类似于运输层报文段中端口号字段所起的作用。
- 协议字段是将网络层与运输层绑定到一起的粘合剂
- 端口号是将运输层和应用层绑定到一起的粘合剂
首部检验和 16 首部检验和用于帮助路由器检测收到的 IP 数据报首部是否发生错误
而对应 IP 数据报中的数据区域校验那是上层协议处理的事情
选项字段 0~40 不常用
数据区域
(也可以称之为有效载荷)
IP 数据报中的数据字段包含要交付给目标 IP 地址的运输层。
数据区域也可承载其他类型的报文,如 ICMP 报文。


数据报在以太网帧上的封装


image.png

IP 数据报分片

image.png
一个主机打算发送 4000 字节的 IP 数据报(20 字节 IP 首部加上 3980 字节 IP 数据区域,
假设没有 IP 数据报首部选项字段),且该数据报必须通过一条 MTU 为 1500 字节的以太网
链路。这就意味着源始 IP 数据报中 3980 字节数据必须被分配为 3 个独立的数据报分片
(其中的每个分片也是一个 IP 数据报)。

假定初始 IP 数据报贴上的标识号为 666

  • 那么第一个分片的数据报总大小为 1500 字节(1480 字节数据大小+20 字节 IP 数据报首部),分片偏移量为 0。
  • 第二个分片的数据报大小也为 1500 字节,分片偏移量为 185(185*8=1480),
  • 第三个分片的数据报大小为 1040(3980-1480-1480+20),分片偏移量为370(185+185)。

校验算法:https://blog.csdn.net/caozhigang129/article/details/82415698

发送端: 将发送的数据以两字节为单位进行补码相加,checksum处设置为0,得到32字节的数,再将底16位和高16位相加,结果求反,即为较验和。

接收端:和发送端相同的算法,checksum处使用发送端的结果进行补码相加,结果求反为0x0000,表明数据传输正确,否则数据传输不正确,舍弃。

  1. static unsigned short chksum(void *dataptr, unsigned short len)
  2. {
  3. unsigned long acc;
  4. unsigned short src;
  5. unsigned char *octetptr;
  6. acc = 0;
  7. octetptr = (unsigned char*)dataptr;
  8. while (len > 1)
  9. {
  10. src = (*octetptr) << 8; //2个字节结合
  11. octetptr++;
  12. src |= (*octetptr);
  13. octetptr++;
  14. acc += src;
  15. len -= 2;
  16. }
  17. if (len > 0) //最后单个字节,补0,组成2字节
  18. {
  19. src = (*octetptr) << 8;
  20. acc += src;
  21. }
  22. printf("acc=%x\n",acc);
  23. if ((acc & 0xffff0000UL) != 0) //高16位 + 低16位
  24. {
  25. acc = (acc >> 16) + (acc & 0x0000ffffUL);
  26. }
  27. src = (unsigned short)acc;
  28. printf("src=%x\n",src);
  29. return ~src;
  30. }