IP 数据包头解析工具

本工具可以帮助您解析 IP 数据包头信息,并以易于理解的方式展示关键参数。

输入 IP 数据包头

请输入您想要分析的 IP 数据包头,例如:

45 00 00 2e 13 23 00 00 80 11 5c 99 c0 a8 01 65 3b 37 cd be

解析结果

版本号: 4 包头长度: 20 字节 优先权: 0 TOS: 一般服务 包总长: 584 字节 标志位: 3523 分片: 可以分片 包属性: 最后一个分片的包 分段偏移: 0 TTL: 1 协议号: 6 (TCP) 头部校验和: 80115c99c0a8 原始地址: 192.168.1.101 目标地址: 59.193.190.230

代码实现

Java 代码

package com.company;

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        //45 00 00 2e 13 23 00 00 80 11 5c 99 c0 a8 01 65 3b 37 cd be
        
        System.out.println('请输入一串IP数据包头:');
        System.out.println();

        Scanner sc = new Scanner(System.in);
        String packet = sc.nextLine().replace(' ', '');
        sc.close();
        //得到所有位数据


        //版本号
        final int version = Integer.parseInt(packet.substring(0, 1), 16);
        //包头长度
        final int headerLength = Integer.parseInt(packet.substring(1, 2), 16) * 4;

        StringBuilder tmp = new StringBuilder(Integer.toBinaryString(Integer.parseInt(packet.substring(2, 4), 16)));
        int len = tmp.length();
        for (int i = 0; i < 8 - len; i++) tmp.insert(0, '0');

        //优先权
        final int priority = Integer.parseInt(tmp.substring(0, 3), 2);
        //最小延时、高吞吐量、最高可靠性、低成本(全为0为普通包,否则只能有一个为1)
        final String TOS;
        if (tmp.charAt(3) == '1') TOS = '最小延迟';
        else if (tmp.charAt(4) == '1') TOS = '最大吞吐量';
        else if (tmp.charAt(5) == '1') TOS = '最高可靠性';
        else if (tmp.charAt(6) == '1') TOS = '低成本';
        else TOS = '一般服务';
        //未使用位
        //IP数据报文总长(包含头部和数据)
        int packetLength = Integer.parseInt(packet.substring(4, 8), 16);
        //标志位(让主机判断这个包属于哪个分组)
        int identification = Integer.parseInt(packet.substring(8, 12), 16);

        tmp = new StringBuilder(Integer.toBinaryString(Integer.parseInt(packet.substring(12, 16), 16)));
        len = tmp.length();
        for (int i = 0; i < 16 - len; i++) tmp.insert(0, '0');
        //未使用, 必须为0
        //是否分片 0:可以 1:不可以
        String section = tmp.charAt(1) == '0' ? '可以分片' : '不能分片';
        //如果分片, 包属于 0:最后一个分片的包 1:分片中段的包
        String property = tmp.charAt(2) == '0' ? '最后一个分片的包' : '分片中段的包';
        //分段偏移
        String fragmentOffset = tmp.substring(3, 16);

        //TTL值
        int ttl = Integer.parseInt(packet.substring(16, 18), 16);
        //协议号
        int protocolCode = Integer.parseInt(packet.substring(18, 20), 16);
        String protocol = '未知';
        for (var val : protocolType.values()) {
                if (val.getValue() == protocolCode)
                        protocol = val.name();
        }

        tmp = new StringBuilder(Integer.toBinaryString(Integer.parseInt(packet.substring(20, 24), 16)));
        len = tmp.length();
        for (int i = 0; i < 16 - len; i++) tmp.insert(0, '0');
        //头部校验和
        String checkSum = tmp.toString();
        //原始地址
        int[] sourceAddress = {
                Integer.parseInt(packet.substring(24, 26), 16),
                Integer.parseInt(packet.substring(26, 28), 16),
                Integer.parseInt(packet.substring(28, 30), 16),
                Integer.parseInt(packet.substring(30, 32), 16)
        };
        //目标地址
        int[] targetAddress = {
                Integer.parseInt(packet.substring(32, 34), 16),
                Integer.parseInt(packet.substring(34, 36), 16),
                Integer.parseInt(packet.substring(36, 38), 16),
                Integer.parseInt(packet.substring(38, 40), 16)
        };

        //输出包信息
        println('版本号:');
        println(String.format('%d', version));
        System.out.println();

        println('包头长度:');
        println(String.format('%d', headerLength));
        System.out.println();

        println('优先权:');
        println(String.format('%d', priority));
        System.out.println();

        println('TOS:');
        println(String.format('%s', TOS));
        System.out.println();

        println('包总长:');
        println(String.format('%d', packetLength));
        System.out.println();

        println('标志位:');
        println(String.format('%d', identification));
        System.out.println();

        println('分片:');
        println(String.format('%s', section));
        System.out.println();

        println('包属性:');
        println(String.format('%s', property));
        System.out.println();

        println('分段偏移:');
        println(String.format('%s', fragmentOffset));
        System.out.println();

        println('TTL:');
        println(String.format('%d', ttl));
        System.out.println();

        println('协议号:');
        println(String.format('%d(%s)', protocolCode, protocol));
        System.out.println();

        println('头部校验和:');
        println(String.format('%s', checkSum));
        System.out.println();

        println('原始地址:');
        println(String.format('%d.%d.%d.%d', sourceAddress[0], sourceAddress[1], sourceAddress[2], sourceAddress[3]));
        System.out.println();

        println('目标地址:');
        println(String.format('%d.%d.%d.%d', targetAddress[0], targetAddress[1], targetAddress[2], targetAddress[3]));
        System.out.println();
    }


    static void println(String msg) {
        System.out.printf('%-15s', msg);
    }

    enum protocolType {
        ICMP(1),
        IGMP(2),
        TCP(6),
        UDP(17);

        private final int index;

        protocolType(int index) {
            this.index = index;
        }

        public int getValue() {
            return index;
        }
    }
}

C 代码

#include <stdio.h>
#include <string.h>

typedef enum {
    ICMP = 1,
    IGMP = 2,
    TCP = 6,
    UDP = 17
} ProtocolType;

void println(const char* msg) {
    printf('%-15s', msg);
}

int main() {
    //45 00 00 2e 13 23 00 00 80 11 5c 99 c0 a8 01 65 3b 37 cd be

    printf('请输入一串IP数据包头:\n\n');

    char packet[40];
    scanf('%s', packet);
    //去除空格
    for (int i = 0, j = 0; i < strlen(packet); i++) {
        if (packet[i] != ' ') {
            packet[j++] = packet[i];
        }
    }
    packet[strlen(packet)] = '\0';

    //版本号
    const int version = packet[0] - '0';
    //包头长度
    const int headerLength = (packet[1] - '0') * 4;

    //优先权
    const int priority = (packet[2] - '0') >> 5;
    //最小延时、高吞吐量、最高可靠性、低成本(全为0为普通包,否则只能有一个为1)
    const char* TOS;
    switch ((packet[2] - '0') & 0x1F) {
        case 0:
            TOS = '一般服务';
            break;
        case 1:
            TOS = '最小延迟';
            break;
        case 2:
            TOS = '最大吞吐量';
            break;
        case 4:
            TOS = '最高可靠性';
            break;
        case 8:
            TOS = '低成本';
            break;
        default:
            TOS = '未知';
            break;
    }
    //未使用位
    //IP数据报文总长(包含头部和数据)
    int packetLength = (packet[4] - '0') * 16 * 16 * 16 + (packet[5] - '0') * 16 * 16 + (packet[6] - '0') * 16 + (packet[7] - '0');
    //标志位(让主机判断这个包属于哪个分组)
    int identification = (packet[8] - '0') * 16 * 16 * 16 + (packet[9] - '0') * 16 * 16 + (packet[10] - '0') * 16 + (packet[11] - '0');

    //是否分片 0:可以 1:不可以
    const char* section = (packet[12] - '0') & 0x02 ? '不能分片' : '可以分片';
    //如果分片, 包属于 0:最后一个分片的包 1:分片中段的包
    const char* property = (packet[12] - '0') & 0x04 ? '分片中段的包' : '最后一个分片的包';
    //分段偏移
    int fragmentOffset = ((packet[12] - '0') & 0x1F) * 16 * 16 + (packet[13] - '0') * 16 + (packet[14] - '0');

    //TTL值
    int ttl = packet[16] - '0';
    //协议号
    int protocolCode = packet[18] - '0';
    const char* protocol = '未知';
    switch (protocolCode) {
        case ICMP:
            protocol = 'ICMP';
            break;
        case IGMP:
            protocol = 'IGMP';
            break;
        case TCP:
            protocol = 'TCP';
            break;
        case UDP:
            protocol = 'UDP';
            break;
    }

    //头部校验和
    char checkSum[17];
    strncpy(checkSum, &packet[20], 16);
    checkSum[16] = '\0';

    //原始地址
    int sourceAddress[4];
    for (int i = 0; i < 4; i++) {
        sourceAddress[i] = (packet[24 + i * 2] - '0') * 16 + (packet[25 + i * 2] - '0');
    }

    //目标地址
    int targetAddress[4];
    for (int i = 0; i < 4; i++) {
        targetAddress[i] = (packet[32 + i * 2] - '0') * 16 + (packet[33 + i * 2] - '0');
    }

    //输出包信息
    println('版本号:');
    println('%d', version);
    printf('\n');

    println('包头长度:');
    println('%d', headerLength);
    printf('\n');

    println('优先权:');
    println('%d', priority);
    printf('\n');

    println('TOS:');
    println('%s', TOS);
    printf('\n');

    println('包总长:');
    println('%d', packetLength);
    printf('\n');

    println('标志位:');
    println('%d', identification);
    printf('\n');

    println('分片:');
    println('%s', section);
    printf('\n');

    println('包属性:');
    println('%s', property);
    printf('\n');

    println('分段偏移:');
    println('%d', fragmentOffset);
    printf('\n');

    println('TTL:');
    println('%d', ttl);
    printf('\n');

    println('协议号:');
    println('%d(%s)', protocolCode, protocol);
    printf('\n');

    println('头部校验和:');
    println('%s', checkSum);
    printf('\n');

    println('原始地址:');
    println('%d.%d.%d.%d', sourceAddress[0], sourceAddress[1], sourceAddress[2], sourceAddress[3]);
    printf('\n');

    println('目标地址:');
    println('%d.%d.%d.%d', targetAddress[0], targetAddress[1], targetAddress[2], targetAddress[3]);
    printf('\n');

    return 0;
}

注意事项

  • 请确保输入的 IP 数据包头信息正确且完整,否则解析结果可能不准确。
  • 本工具仅解析 IP 数据包头信息,不解析数据包的有效负载。
  • IP 数据包头解析结果仅供参考,具体含义请参考相关网络协议文档。
IP数据包头解析工具 - 在线分析 IP 数据包头信息

原文地址: https://www.cveoy.top/t/topic/fkWp 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录