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
    
  • 相关阅读:
    漂亮灵活设置的jquery通知提示插件toastr
    C# 对List<T>取交集、连集及差集
    查看sqlserver被锁的表以及如何解锁.
    javascript的setTimeout()用法总结,js的setTimeout()方法
    日志插件 log4net 的使用
    Log4NET简介
    解决WCF大数据量传输 ,System.Net.Sockets.SocketException: 远程主机强迫关闭了一个现有的连接
    也说Autofac在MVC的简单实践:破解在Controller构造函数中的实例化
    Autofac 依赖注入 ASP.NET MVC5 插件机制中插件的简单实现
    Asp.net mvc中整合autofac
  • 原文地址:https://www.cnblogs.com/chiaki/p/13554706.html
Copyright © 2011-2022 走看看