IP头部结构

IP头部由头部和数据段组成,包含版本、头部长度、服务类型、总长度、标识符、标志、分片偏移量、剩余生存时间TTL、协议、头部校验和等字段。这些字段在确保数据传输、分片处理、路由选择和错误检测等方面起到关键作用。
部署运行你感兴趣的模型镜像

 

IP头部结构

 

       RFC 751定义了因特网协议,IP是一个无连接的协议,这意味着它将每个IP分组都看成是与其他IP分组无关的独立数据单元。IP不具备通常为了确保数据的认证机制,如果再分组转发过程中发生错误,IP不会启动任何动作来更正这个错误。分组头部的字段和为之服务的协议功能的复杂度之间存在着直接的联系,头部越简单,相应的协议越简单。

 

      

IP头部由头部和数据段组成

头部包含有下列字段:版本(version),该字段占用4位以申明IP版本。目前广泛使用的是IPv4,然而新版本的IPv6正在逐渐的被更多的使用。

 

头部长度(header length)

IP分组的头部长度占用4位,他使用32位字度量头部长度,通常,头部由20个字节长(5个32位字),然而,如果增加了控制信息,那么通过附加IP可选字段,长度会进一步增加。头部的最大长度为60字节。

 

服务类型(Tos)(Type Of Service)

       或者称呼它的新名字---区别服务字节(differrntiated service byte)(DS 字节)。该字段占用1个字节,与之对应的两个变量:Tos(以前名称)和DS字节(新名称),不管哪种情况,这个字段用来存储反映分组Qos需求的参数。

       在Tos中,这个字段被分为两个子字段,其实的3位组成优先权子字段,优先权可取值0(普通分组)到7(控制信息分组)。路由器和计算机会考虑分组的优先权从而优先处理最高优先级的分组。Tos字段还包括3位用来判断路由选择策略(route selection criterion),有三个选项:低延迟、高可靠性或高吞吐量。如果delay(D)位设为1,那么在传送这个分组时路由应该选择将延时最小化。吞吐量(T)位会最大化吞吐量,可靠性(R)位会最大化可靠性。剩余2位是保留为,通常设为0. DS字节只使用该字节的高6位,保留低2位。

     

总长度(total length)

       这个字段占用2个字节,申明分组的总长度,包括头部和数据段。分组最大长度受限于该字段的长度,即65535个字节。然而,多数网络并不适用如此长的分组。以太网帧最大分组长度为1500字节,TCP/IP标准确保所有主机有能力接受576个字节长的分组(无论他们是否分片)。

 

标识符(identification)

      这个字段占用2个字节,用来识别源分组分片所创建的分组,同一个分组的各个分片必须具有形同的标识符值。

 

标志(flags)

       标志占用3位,包含与分片相关的属性。将部分片(do not fragment,DF)位设为1提示路由器不要将此分组分片。但若多片(more fragment,MF)位被设置为1,就意味着此分组被分片且不是最后一片。剩余位属于保留位。

 

分片偏移量(fragment offset)

       该字段占用13位,申明该分组中数据区域相对于分片源分子的数据起点的偏移量,它用于组装或重新组装分组时用,偏移量必须为8的倍数。

 

剩余生存时间(time to live)TTL

        该字段占用1字节,用于指明分组在网络上传输的最大时间间隔,TTL以秒为单位,由发送端指定。分组的当前TTL随着它花费在网络传输中途径的每个路由器上的每一秒递减一。即使路由器处理分组的时间不足一秒,还是必须将TTL计数器减一。因为如今的路由器处理分组极少花费多于1秒的时间。TTL可以被解释分组路过的转换节点数。如果TTL值在到达目的地之前将为0,则丢弃该分组。因此TTL参数是分组的一种“自我破坏”的计时器。

 

协议(protocol)

       该字段占用1字节,包括了数据字段中的信息所要传递的高一层协议的标识符。不同协议的标识符在“分配号码”RFC 1340中列出。序列号16代表TPC分组消息,17代表UDP,1代表ICMP。

 

 

头部校验和(header checksum)

        这个字段占用2个字节,只计算头部的校验和。因为有些头部字段在网络传输过程中会改变(如 TTL),必须检查校验和并在每个路由器和终端节点上重新计算。校验和---16位---计算头部中所有16位字和的补码。在计算校验和时,头部校验和字段被设为零。如果校验和不正确,将会报告错误,那么该分组在错误被发现的同时被丢弃。

    

 

 

源IP地址(Source IP Address)和目的IP地址(Destination IP Address)

这两个字段长度相同--32位。

 

IP选项(IP Optitions)

       这个字段是可选的。原则上是在网络纠错时才使用。该字段包含好多个子字段,每个具有八个预设类型。在这些字段中,可以指定途径路由器的准备路由,注册分组路过的路由器,存储安全系统数据或保存时间戳。

 

 

填充(padding)

       既然IP选项字段的子字段数是任意的,但有必要在分组头部的最后增加几个字节以将分组对齐到32位边界。这个字段都用0来填充。

 

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

# IPv4头部结构详解 **核心答案:IPv4头部是一个20-60字节的结构,包含版本、首部长度、服务类型、总长度、标识、标志、片偏移、生存时间、协议、首部校验和、源IP地址和目的IP地址等字,用于IP数据包的路由和传输。** ## 完整的IPv4头部结构 ### 1. **基本结构定义** ```c #include <stdint.h> // IPv4头部结构 - 网络字节序 typedef struct { uint8_t version_ihl; // 版本 + 首部长度 (1字节) uint8_t tos; // 服务类型 (1字节) uint16_t total_length; // 总长度 (2字节,网络字节序) uint16_t id; // 标识 (2字节,网络字节序) uint16_t flags_offset; // 标志 + 片偏移 (2字节,网络字节序) uint8_t ttl; // 生存时间 (1字节) uint8_t protocol; // 协议 (1字节) uint16_t checksum; // 首部校验和 (2字节,网络字节序) uint32_t src_addr; // 源IP地址 (4字节,网络字节序) uint32_t dst_addr; // 目的IP地址 (4字节,网络字节序) // 可选字和填充 (0-40字节) } __attribute__((packed)) ip4_header_t; ``` ### 2. **位级结构图解** ``` 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Version| IHL |Type of Service| Total Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identification |Flags| Fragment Offset | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Time to Live | Protocol | Header Checksum | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Source Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Destination Address | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Options | Padding | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` ## 详细代码实现 ### 1. **IPv4头部字段定义** ```c // IPv4版本和首部长度掩码 #define IP4_VERSION_MASK 0xF0 // 高4位: 版本 #define IP4_IHL_MASK 0x0F // 低4位: 首部长度 #define IP4_VERSION_4 0x40 // IPv4 (4 << 4) #define IP4_MIN_HEADER_LENGTH 5 // 最小首部长度(以32位字为单位) #define IP4_MAX_HEADER_LENGTH 15 // 最大首部长度(以32位字为单位) // 服务类型(TOS)字 #define IP4_TOS_PRECEDENCE_MASK 0xE0 // 优先级 (高3位) #define IP4_TOS_DSCP_MASK 0xFC // DSCP (高6位) #define IP4_TOS_ECN_MASK 0x03 // ECN (低2位) // 服务类型优先级 #define IP4_TOS_ROUTINE 0x00 // 常规 #define IP4_TOS_PRIORITY 0x20 // 优先 #define IP4_TOS_IMMEDIATE 0x40 // 立即 #define IP4_TOS_FLASH 0x60 // 闪速 #define IP4_TOS_FLASH_OVERRIDE 0x80 // 闪速覆盖 #define IP4_TOS_CRITIC_ECP 0xA0 // 关键ECO #define IP4_TOS_INET_CONTROL 0xC0 // 互联网控制 #define IP4_TOS_NET_CONTROL 0xE0 // 网络控制 // 标志位 #define IP4_FLAG_RF 0x8000 // 保留位 #define IP4_FLAG_DF 0x4000 // 不分片 #define IP4_FLAG_MF 0x2000 // 更多分片 #define IP4_FRAGMENT_OFFSET_MASK 0x1FFF // 分片偏移掩码 // 常见协议类型 #define IP4_PROTOCOL_ICMP 1 // Internet Control Message #define IP4_PROTOCOL_IGMP 2 // Internet Group Management #define IP4_PROTOCOL_TCP 6 // Transmission Control #define IP4_PROTOCOL_UDP 17 // User Datagram #define IP4_PROTOCOL_GRE 47 // General Routing Encapsulation #define IP4_PROTOCOL_IPSEC_AH 51 // IP Security Authentication Header #define IP4_PROTOCOL_IPSEC_ESP 50 // IP Security Encapsulating Security Payload #define IP4_PROTOCOL_PPTP 47 // PPTP (使用GRE) ``` ### 2. **IPv4头部操作函数** ```c // 获取版本号 uint8_t ip4_get_version(const ip4_header_t *ip4) { return (ip4->version_ihl & IP4_VERSION_MASK) >> 4; } // 获取首部长度(字节数) uint8_t ip4_get_header_length(const ip4_header_t *ip4) { uint8_t ihl = ip4->version_ihl & IP4_IHL_MASK; return ihl * 4; // 转换为字节数 } // 设置首部长度 void ip4_set_header_length(ip4_header_t *ip4, uint8_t bytes) { if (bytes % 4 != 0) { // 长度必须是32位字的倍数 bytes = (bytes + 3) & ~3; } uint8_t words = bytes / 4; if (words < IP4_MIN_HEADER_LENGTH || words > IP4_MAX_HEADER_LENGTH) { return; // 无效长度 } ip4->version_ihl = (ip4->version_ihl & IP4_VERSION_MASK) | words; } // 初始化IPv4头部 void ip4_init_header(ip4_header_t *ip4, uint16_t payload_len, uint8_t protocol, uint32_t src_addr, uint32_t dst_addr) { // 清零 memset(ip4, 0, sizeof(ip4_header_t)); // 版本和首部长度 ip4->version_ihl = IP4_VERSION_4 | IP4_MIN_HEADER_LENGTH; // 服务类型 ip4->tos = 0; // 总长度 ip4->total_length = htons(sizeof(ip4_header_t) + payload_len); // 标识(通常由系统生成) ip4->id = htons(0); // 实际使用时应设置唯一值 // 标志和分片 ip4->flags_offset = 0; // 默认不分片 // TTL ip4->ttl = 64; // 默认TTL // 协议 ip4->protocol = protocol; // 源和目的地址 ip4->src_addr = src_addr; ip4->dst_addr = dst_addr; // 计算校验和 ip4->checksum = 0; ip4->checksum = ip4_checksum(ip4); } ``` ### 3. **校验和计算** ```c // 计算IPv4首部校验和 uint16_t ip4_checksum(const ip4_header_t *ip4) { const uint16_t *data = (const uint16_t *)ip4; int len = ip4_get_header_length(ip4); uint32_t sum = 0; // 计算所有16位字的和 for (int i = 0; i < len / 2; i++) { sum += ntohs(data[i]); } // 处理奇数字节 if (len % 2 == 1) { uint8_t last_byte = ((const uint8_t *)data)[len - 1]; sum += last_byte << 8; } // 折叠32位和到16位 while (sum >> 16) { sum = (sum & 0xFFFF) + (sum >> 16); } // 取反得到校验和 return htons(~sum); } // 验证校验和 bool ip4_verify_checksum(const ip4_header_t *ip4) { uint16_t original_checksum = ip4->checksum; uint16_t calculated = ip4_checksum(ip4); return original_checksum == calculated; } ``` ### 4. **分片处理** ```c // 检查是否需要分片 bool ip4_needs_fragmentation(const ip4_header_t *ip4, uint16_t mtu) { uint16_t total_len = ntohs(ip4->total_length); uint16_t header_len = ip4_get_header_length(ip4); return (total_len > mtu) && !(ntohs(ip4->flags_offset) & IP4_FLAG_DF); } // 创建分片 ip4_header_t* ip4_create_fragment(const ip4_header_t *original, uint16_t offset, uint16_t frag_size, bool more_fragments) { ip4_header_t *frag = malloc(sizeof(ip4_header_t)); if (!frag) return NULL; // 复制原始头部 memcpy(frag, original, sizeof(ip4_header_t)); // 更新总长度 frag->total_length = htons(frag_size + ip4_get_header_length(frag)); // 设置分片信息 uint16_t flags_offset = (offset / 8) & IP4_FRAGMENT_OFFSET_MASK; if (more_fragments) { flags_offset |= IP4_FLAG_MF; } frag->flags_offset = htons(flags_offset); // 重置和重新计算校验和 frag->checksum = 0; frag->checksum = ip4_checksum(frag); return frag; } ``` ### 5. **选项处理** ```c // IPv4选项类型 #define IP4_OPTION_END_OF_LIST 0 // 结束列表 #define IP4_OPTION_NO_OPERATION 1 // 无操作 #define IP4_OPTION_SECURITY 2 // 安全 #define IP4_OPTION_LOOSE_SOURCE_ROUTE 3 // 松散源路由 #define IP4_OPTION_STRICT_SOURCE_ROUTE 7 // 严格源路由 #define IP4_OPTION_RECORD_ROUTE 7 // 记录路由 #define IP4_OPTION_STREAM_ID 8 // 流ID #define IP4_OPTION_TIMESTAMP 68 // 时间戳 // 选项结构 typedef struct { uint8_t type; uint8_t length; uint8_t data[1]; // 可变长度 } __attribute__((packed)) ip4_option_t; // 解析选项 void ip4_parse_options(const ip4_header_t *ip4) { uint8_t header_len = ip4_get_header_length(ip4); if (header_len <= sizeof(ip4_header_t)) { return; // 无选项 } const uint8_t *options = (const uint8_t *)(ip4 + 1); uint8_t options_len = header_len - sizeof(ip4_header_t); printf("解析IPv4选项 (%u 字节):\n", options_len); for (uint8_t i = 0; i < options_len; ) { uint8_t opt_type = options[i]; switch (opt_type) { case IP4_OPTION_END_OF_LIST: printf(" END_OF_LIST\n"); return; // 结束 case IP4_OPTION_NO_OPERATION: printf(" NO_OPERATION\n"); i += 1; break; default: if (i + 1 >= options_len) { printf(" 无效选项格式\n"); return; } uint8_t opt_len = options[i + 1]; if (opt_len < 2 || i + opt_len > options_len) { printf(" 无效选项长度\n"); return; } printf(" Type=%u, Length=%u", opt_type, opt_len); // 打印数据 if (opt_len > 2) { printf(", Data:"); for (int j = 2; j < opt_len; j++) { printf(" %02X", options[i + j]); } } printf("\n"); i += opt_len; break; } } } ``` ### 6. **完整演示程序** ```c void demonstrate_ip4_header() { printf("=== IPv4头部结构演示 ===\n\n"); // 分配IPv4头部 ip4_header_t *ip4 = malloc(sizeof(ip4_header_t)); if (!ip4) { printf("内存分配失败\n"); return; } // 初始化头部 ip4_init_header(ip4, 1000, // 负载长度 IP4_PROTOCOL_TCP, // 协议 0xC0A80101, // 源IP: 192.168.1.1 0xC0A80164); // 目的IP: 192.168.1.100 // 显示头部信息 printf("IPv4头部信息:\n"); printf(" 版本: %u\n", ip4_get_version(ip4)); printf(" 首部长度: %u 字节\n", ip4_get_header_length(ip4)); printf(" TOS: 0x%02X\n", ip4->tos); printf(" 总长度: %u 字节\n", ntohs(ip4->total_length)); printf(" 标识: %u\n", ntohs(ip4->id)); printf(" TTL: %u\n", ip4->ttl); printf(" 协议: %u", ip4->protocol); switch (ip4->protocol) { case IP4_PROTOCOL_TCP: printf(" (TCP)"); break; case IP4_PROTOCOL_UDP: printf(" (UDP)"); break; case IP4_PROTOCOL_ICMP: printf(" (ICMP)"); break; default: printf(" (?)"); break; } printf("\n"); printf(" 校验和: 0x%04X\n", ntohs(ip4->checksum)); printf(" 源IP: %u.%u.%u.%u\n", (ip4->src_addr >> 24) & 0xFF, (ip4->src_addr >> 16) & 0xFF, (ip4->src_addr >> 8) & 0xFF, ip4->src_addr & 0xFF); printf(" 目的IP: %u.%u.%u.%u\n", (ip4->dst_addr >> 24) & 0xFF, (ip4->dst_addr >> 16) & 0xFF, (ip4->dst_addr >> 8) & 0xFF, ip4->dst_addr & 0xFF); // 显示十六进制 printf("\n十六进制表示:\n"); uint8_t *bytes = (uint8_t *)ip4; for (int i = 0; i < sizeof(ip4_header_t); i++) { printf("%02X ", bytes[i]); if ((i + 1) % 16 == 0) printf("\n"); } printf("\n"); // 验证校验和 if (ip4_verify_checksum(ip4)) { printf("\n✓ 校验和验证通过\n"); } else { printf("\n✗ 校验和验证失败\n"); } free(ip4); } ``` ### 7. **实际网络抓包示例** ```hex ; 典型的IPv4+TCP包 (Wireshark导出) 0000 45 00 00 3C 12 34 40 00 40 06 B9 ED C0 A8 01 01 E..<.4@.@....... ^^ <- Version=4, IHL=5 (20字节头部) ^^ <- TOS=0 ^^ ^^ <- Total Length=60 ^^ ^^ ^^ ^^ <- Identification=0x1234 ^^ <- Flags=0x40 (DF=1), Fragment Offset=0 ^^ <- TTL=64 ^^ <- Protocol=6 (TCP) ^^ ^^ <- Header Checksum ^^ ^^ ^^ ^^ <- Source IP ^^ ^^ ^^ ^^ <- Dest IP ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值