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
    
  • 相关阅读:
    2017年8月27日 星期日 --出埃及记 Exodus 29:6
    2017年8月26日 星期六 --出埃及记 Exodus 29:5
    2017年8月25日 星期五 --出埃及记 Exodus 29:4
    2017年8月24日 星期四 --出埃及记 Exodus 29:3
    2017年8月23日 星期三 --出埃及记 Exodus 29:2
    2017年8月22日 星期二 --出埃及记 Exodus 29:1
    2016年12月总结
    2016年11月总结
    2016年10月总结
    项目风险说明
  • 原文地址:https://www.cnblogs.com/chiaki/p/13554706.html
Copyright © 2011-2022 走看看