网络协议包格式

网上找到了一张数据帧表示图

 在linux系统中,使用struct ethhdr结构体来表示以太网帧的头部。这个struct ethhdr结构体位于#include<linux/if_ether.h>之中。

#define ETH_ALEN 6 //定义了以太网接口的MAC地址的长度为6个字节

#define ETH_HLAN 14 //定义了以太网帧的头长度为14个字节

#define ETH_ZLEN 60 //定义了以太网帧的最小长度为 ETH_ZLEN + ETH_FCS_LEN = 64个字节

#define ETH_DATA_LEN 1500 // 定义了以太网帧的最大负载为1500个字节

#define ETH_FRAME_LEN 1514 // ETH_HLAN + ETH_DATA_LEN

#define ETH_FCS_LEN 4 //定义了以太网帧的CRC值占4个字节

以太网帧的最短长度为64字节,或者帧中的数据不得少于46个字节,其中以太网帧头有18字节

ETH_ALEN * 2 + 2字节类型 = 18字节

注意如果是802.3的规范,它支持SNAP和802.3以太,其中的2个字节的类型字段就变为帧的长度,小于以上长度的帧或数据需要在帧中加入“填充数据(pad)” 。

以太网帧的最长长度为1518字节。我们所说的MTU 以太网一般为1500,加上以太网帧头18字节。

ETH_HLAN + ETH_DATA_LEN + ETH_FCS_LEN = 1518字节

注意,802.3规范已经把最大长度改为1536(0x0600)了。

struct ethhdr
{
  unsigned char h_dest[ETH_ALEN]; //目的MAC地址
  unsigned char h_source[ETH_ALEN]; //源MAC地址
  __u16 h_proto ; //网络层所使用的协议类型
} __attribute__((packed)) //用于告诉编译器不要对这个结构体中的缝隙部分进行填充操作;

#define  ETH_P_IP 0x0800 //IP协议

#define  ETH_P_ARP 0x0806  //地址解析协议(Address Resolution Protocol)

#define  ETH_P_RARP 0x8035  //返向地址解析协议(Reverse Address Resolution Protocol)

#define  ETH_P_IPV6 0x86DD  //IPV6协议

struct iphdr {

#if defined(__LITTLE_ENDIAN_BITFIELD)

  __u8 ihl:4,

  version:4;

#elif defined (__BIG_ENDIAN_BITFIELD)

  __u8 version:4,

  ihl:4;

#else

#error "Please fix <asm/byteorder.h>"

#endif

  __u8 tos;
    
  __be16 tot_len;

  __be16 id;

  __be16 frag_off;

  __u8 ttl;

  __u8 protocol;

  __sum16 check;

  __be32 saddr;

  __be32 daddr;

  /*The options start here. */ 

};

iphdr->version

版本(4位),目前的协议版本号位4,也称之为IPv4

iphdr->ihl

首部长度(4位),首部长度是指IP层头部占32bit字的数目,也就是IP层头部包含多少个4字节(32b),包括任何选项,由于它是一个4bit(最大表示15)字段,因此首部最长为15 *4 = 60个字节。普通IP数据报字段的值为5 ==》5*32/8=20Bytes

iphdr->tos

服务类型字段(8位):服务类型(TOS)字段包括一个3bit的优先权字段(已被忽略),4bit的TOS子字段和1bit未用位但必须置0。4bit的TOS子字段分别表示最小时延、最大吞吐量、最高可靠性和最小费用。4bit中只能设置1bit。如果4bit均为0表示这是一般服务。

iphdr->tot_len

总长度字段(16)位指的是整个IP数据包的长度(首部+数据部分),以字节为单位。利用首部长度字段和总长度字段,就可以知道IP数据报中数据内容的起始位置和长度。由于该字段长16bit,所以IP数据包最长可长达65535字节。

总长度字段是IP首部中必要的内容,因为一些数据链路(如以太网)需要填充一些数据以达到最小长度。尽管以太网的最小帧长为46字节,但IP数据可能更短。如果没有总长度字段,那么IP层就不知道46字节中有多少是IP数据报的内容。

iphdr->id

标识字段(16bit)唯一地标识主机发送地每一份数据报,通常每发送一份报文他的值就加1。

iphdr->frag_off

frag_off低13位

标识分段偏移(Fragment offset)域指明了该分段在当前数据报中的什么位置上。除了一个数据报的最后一个分段以外,其他所有的分段(分片)必须是8字节的倍数。这是8字节是基本分段单位。由于该域有13个位,所以每个数据报最多有8192个分段。因此最大数据报长度为65536字节,比iphdr->tot_len域还大1。

frag_off高3位:

l  比特0保留,必须为0;

l  比特1是“更多分片”(MF—More Fragment)标志。除了最后一片外,其他每个组成数据报的片都要把该比特置1.

l  比特2是“部分片”(DF—Don’t Fragment)标志,如果将这一比特置1,IP将不对数据报进行分片,这是如果需要进行分片的数据报到来,会丢弃此数据报并发送一个ICMP差错报文给起始端。

iphdr->ttl

TTL(Time to live)8位,生存时间字段设置了数据报可以经过的最多路由器数。它指定了数据报的生存时间。TTl的初始值由源主机设置(通常为32或64),一旦经过一个处理它的路由器,它的值就减去1。当该字段值为0时,数据报就被丢弃,并发送ICMP报文通知源主机。

TTL(Time to live)域是一个用于限制分组生存期的计数器。这里的计数单位为秒,因此最大生存期为255s。在每一跳上该计数器必须被递减。而且数据报在一台路由器上排队时间较长时,该计数器必须被多倍递减。在实践中,当它递减到0时,分组会被丢弃,路由器给源主机发送一个警告分组。此项特性可以避免数据报长时间地逗留在网络中。

iphdr->protocol

协议字段(8位):根据它可以识别是哪个协议向IP传送数据。

当网络层组装完成一个完整地数据报之后,他需要知道该如何对它进行处理。协议(Protocol)域指明了该将它交给哪个传输进程。TCP或者UDP或者其他协议。

iphdr->check

首部校验和字段(16)位时根据IP首部计算的校验和码。他不对首部后面的数据进行计算。ICMP、IGMP、UDP、TCP在它们各自的首部中均含有同时覆盖首部和数据校验和码。

为了计算一份数据报的IP校验和,首先把校验和字段置为0。然后对首部中每个16bit进行二进制反码求和(整个首部看出时一串16bie的字组成),结果存在校验和字段中。当收到一份IP数据报后,同样对首部中的每个16bit进行二进制反码求和。由于接收方在计算过程中包含了发送方存在首部中的校验和,因此如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该全为1。否则就意味着数据在传输过程中发生错误,IP就会丢弃收到的数据报。但是不生成差错报文,由上层区发现丢失的数据报并进行重传。

iphdr->saddr

32源IP地址

iphdr->daddr

32位目的IP地址

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值