zoukankan      html  css  js  c++  java
  • 理解传输层中UDP协议首部校验和以及校验和计算方法的Java实现

    UDP,全称User Datagram Protocol,用户数据报协议,是TCP/IP四层参考模型中传输层的一种面向报文的、无连接的、不能保证可靠的、无拥塞控制的协议。UDP协议因为传输效率高,常用于即时通信,比如视频/语音聊天,直播等。

    1. UDP数据报的格式

    用户数据报UDP有两个字段:数据字段和首部字段。首部字段很简单,只有8个字节,有四个字段组成,每个字段的长度都是两字节。各段意义如下:

    • 源端口:源端口号。在需要对方回信时选用。不需要时可用全0。
    • 目的端口:目的端口号。这在终点交付报文时必须要使用到。
    • 长度:UDP用户数据报的长度,其最小值是8(仅首部)。
    • 校验和:检测UDP用户数据报在传输中是否有错。有错就丢弃。

    image-20200824162351771

    2. UDP校验和的计算

    UDP的校验和需要计算UDP首部加数据荷载部分,但也需要加上UDP伪首部。这个伪首部指,源地址、目的地址、UDP数据长度、协议类型(0x11),协议类型就一个字节,但需要补一个字节的0x0,构成12个字节。伪首部+UDP首部+数据一起计算校验和。

    UDP检验和的计算方法是:

    • 按每16位求和得出一个32位的数;
    • 如果这个32位的数,高16位不为0,则高16位加低16位再得到一个32位的数;
    • 重复第2步直到高16位为0,将低16位取反,得到校验和。

    3. UDP校验和计算方法的Java实现

    一个实际例子:

    key hex
    源IP地址 0x0aaa, 0x3bbf
    目的IP地址 0xd20e, 0x960d
    协议类型 0x0011
    UDP长度 0x001c
    源端口 0xd123
    目的端口 0x2742
    长度 0x001c
    校验和 0x285c(用于验证)
    UDP数据 0x0000, 0x6c41, 0x5661, 0x0000, 0x0e00, 0xf8b6, 0xd401, 0x9313, 0x0000, 0x0000, 0x0000

    Java实现:

    public class CheckSumDemo {
        public static void main(String[] args) {
            /**
             * 源IP
             * 目的IP
             * 协议类型
             * UDP数据长度
             * 源端口
             * 目的端口
             * UDP数据
             * UDP数据
             */
            int[] udp = {
                    0x0aaa, 0x3bbf,
                    0xd20e, 0x960d,
                    0x0011,
                    0x001c,
                    0xd123,
                    0x2742,
                    0x001c,
                    0x0000,0x6c41,0x5661,0x0000,0x0e00,0xf8b6,0xd401,0x9313,0x0000,0x0000,0x0000
            };
            int checkSum = 0x285c;
    
            String s = udpCheckSum(udp);
            System.out.println(s);
            System.out.println(Integer.toHexString(checkSum).equals(s));
        }
    
        public static String udpCheckSum(int[] nums) {
            int res = 0;
            for (int num : nums) {
                res += num;
                if (res >>> 16 != 0) {
                    res = (res >>> 16) + (res & 0xffff);
                }
            }
            return Integer.toHexString(~res).substring(4);
        }
    }
    

    结果输出:

    285c
    true
    
  • 相关阅读:
    学习笔记datatablexml转换
    立即执行函数
    MySQL基操—1.Linux下安装(CentOS6/7yum、rpm、tar)
    Linux1.11.shell(环境变量配置文件)
    三国HR评估报告
    毕业5年后拉开差距的原因
    职业的选择
    WPF图片的缩放节省内存
    .asmx支持post请求或者get请求调用
    ionic3遇到的刷新页面服务器关闭的问题
  • 原文地址:https://www.cnblogs.com/chiaki/p/13554706.html
Copyright © 2011-2022 走看看