精华内容
下载资源
问答
  • ip首部校验和

    2021-09-02 15:48:07
    ip首部校验和 只检验数据报的首部,不包括数据部分 方法: 在发送方,先把IP数据报首部划分为许多16位字的序列,并把检验和字段置0,用反码算术运算把所有16位字相加后,将得到的和的反码写入检验和字段。 接收方...

    ip首部校验和

    只检验数据报的首部,不包括数据部分

    方法:

    在发送方,先把IP数据报首部划分为许多16位字的序列,并把检验和字段置0,用反码算术运算把所有16位字相加后,将得到的和的反码写入检验和字段。

    接收方收到数据报后,将首部的所有16位字再使用反码算术运算相加一次。将得到的和取反码,即得出接收方的检验和的计算结果。

    若首部未发生任何变化,则此结果必为0。

    UDP校验和

    与IP校验和类似,但UDP的检验和是把首部和数据部分一起都检验。
    *在计算检验和时,要在UDP用户数据报之前增加12字节的伪首部。

    方法:

    在发送方,首先是把全零放入检验和字段。再把伪首部以及UDP用户数据报看成是由许多16位的字符串接起来的。(若UDP用户数据报的数据部分不是偶数个字节,则要填入一个全零字节)。然后按二进制反码计算出这些16位字的和。将此和的反码写入检验和,发送出去。

    在接收方,把收到的UDP用户数据报连同伪首部一起,按二进制反码求这些16位字的和。当无差错时其结果应为全1.

    TCP校验和

    与UDP类似。

    展开全文
  • IP首部校验和相对简单,在不是特殊类型包的情况下,IP首部长度为20字节,IP校验和就是计算这20位的校验和;TCP校验和,TCP校验和不仅要校验20位的TCP首部与TCP首部后面的数据,还要在TCP首部前加上两个IP(每个IP...

    首先,关于IP和TCP校验和的概念

    IP首部的校验和相对简单,在不是特殊类型包的情况下,IP首部长度为20字节,IP校验和就是计算这20位的校验和;TCP校验和,TCP校验和不仅要校验20位的TCP首部与TCP首部后面的数据,还要在TCP首部前加上两个IP(每个IP四个字节)、十六位的TCP协议(为0x0006)、TCP首部与数据部分的字节数(即TCP首部和数据加起来的长度)组成的伪头。

    IP校验和的计算:

    发送端,

    计算前,先把IP首部校验和设为0,然后将20字节的IP首部视为10个十六位的数值,从前(底层方向为前)往后每一位相加,相加的结果存入一个32位的变量;如果IP首部是特殊类型包,字节数不为20(可能21、23、27谁知道,都有可能),它剩下一个奇数位(它是一个8位的数值),扩展成一个16位的数(后面填充8位的0),把这个新生的16位数加入到前面的和里面。

    得到这样一个和,再把这个和(32位的数值)的高16位与低16位相加,如果和的结果里,高16仍然不等于0,那么再把高16位与低16位相加,直到高16位为0。

    这样一个数值它是一个16位的数,把它以二进制按位取反(比如一个4位的数值,1010按位取反就是0101),按位取反以后的数,就是发送端的校验和,把这个校验和填入IP首部校验和位置。

    接收端,

    接收端计算校验和,接收端收到的包里,已经填入了发送端填写的校验和,这个不用改。计算的规则和发送端一样,都是视为16位的数值,一一相加,奇数位扩展成16位的数值,加入和里面,再把高16位与低16位反复相加,得到一个16位的和,把这个和按位取反。

    这里如果数据包的IP首部正确,那么计算结果就是0(这就是校验和的意义,发送端填入的校验和,接收端计算的时候将校验和计算在里面,结果如果为0,数据包的IP首部就是正确无误的)

     

    //一个实例,以下实例原代码是从51单片机的程序里面拷过来的,在这里要感谢这位LiZhanglin前辈,他的程序给了我很多帮助。
    
    //u_int8_t、u_int16_t 、u_int32_t分别为无符号的8位数、16位数、32位数
    
    
    u_int16_t  CheckSum(u_int16_t * buff, u_long size, u_long InSum)//buff是指向IP首部的指针,InSum是一个初始值,如果是计算IP首部,它的值就为0
    {
        u_int8_t *buf;//这个指针应该没什么用
        u_int32_t cksum = InSum;//把初始值赋值给用于求和的32位变量
       
        u_int16_t  * EndBuf = (u_int16_t *)buff + size / 2;//将IP首部结束位置赋值给一个16位指针,(如果IP首部长度为奇数,它指向的就是最后一个奇数位;如果IP首部长度为偶数,它指向的就是IP首部第20个字节(假设是20字节)的后一位,即实际上就是TCP头、UDP头、ICMP头的位置)
        while (buff < EndBuf)
        {
            cksum += ntohs(*(buff));//相加,这里要注意的,网络上通信用的都是大端序的存储方式,但是我们很多家用计算机里面都是小端序,我这里就必须通过ntohs将网络通信的格式转成我计算机里的格式,否则相加的和就会不正确
            buff++;
        }
        
        if ((size & 0x0001) != 0)//用一个与运算,IP首部字节数是否是奇数
        {
            cksum += ntohs((*buff)) & 0xff00;//是奇数,就将buff指针指向的数值与运算以后加入到和里面(这里buff指针是一个16位的指针,所以它所指的值,是IP首部的奇数位与后面TCP头或UDP头或ICMP头的头一个字节组合起来的16位数,需要把这个16位数的低8位置为0,变相达到将奇数位扩充为16位数的效果,这里的办法是与运算一个0xff00的十六位数;同样这里也要注意大小端序的问题)
        }
            
        cksum = (cksum >> 16) + (cksum & 0xffff);//高低16位反复相加,网上说,这样两句代码与循环将高低16位数相加的效果是一样的,最后结果都是一个16位的数,这应该是一个数学问题,有兴趣的哥哥姐姐可以去找找原因
        cksum += (cksum >> 16);
        
        return (u_int16_t)(~cksum);//将和按位取反,返回一个16位的数
    }

     

    TCP首部的校验和:

    发送端

    发送端将TCP首部的校验和位置设为0。

    先计算伪首部,伪首部由发送端的IP+接收端的IP+TCP协议序号(0x0006)+TCP首部与数据的字节数组成,它并不是一个存在于数据包里的东西,而是一个我们为了方便计算而假设的一个首部,计算方式也是视为16位的数,一个个相加。

    加完伪首部,加TCP首部和数据部分,同样视为16位的数值,一个个相加,如果最后TCP首部和数据部分字节数为奇数位,将奇数位扩充为低8位为0的16位数,加入和里面。

    和的高低16位反复相加,得到一个16位数值,按位取反,返回。

     

    接收端

    计算方式同上,计算结果为0,说明伪头、TCP头、数据没有问题。

     

    实例(我删改了部分注释,删掉了部分多余代码,也可能它并不多余,大家就着原理理解好了,真的缺了什么,自己补吧):

    u_int16_t TCPCheckSum(struct ip_header * pIPHead, u_int16_t TCPSize)//参数:指向IP首部的指针,TCP首部与数据的字节数
    {
        u_long sum = 0;
        u_int16_t  * p;
        u_int16_t i;
        u_int8_t buf[2000];
        
        
        sum = 0;
    
        //虽然不知道是不是我想多了,万一最后一位奇数位后面超出边界怎么办?所以我的想法是复制到一个数组里再计算
        memset(buf, 0x00, 2000);//初始化为0
        memcpy(buf,(u_int8_t*)&(pIPHead->ip_souce_address), 8);//两个IP共占据8个字节
    
        p = (u_int16_t *)buf;
        for (i = 0; i < sizeof(u_int32_t) / sizeof(u_int16_t) * 2; i++, p++) {
            sum += ntohs(*p);//加上两个IP,注意大小端序问题
        }
            
        //sum += (u_int16_t)pIPHead->ip_protocol;
        sum += 0x0006;//反正TCP的协议是0006,加上协议序号
      
        
        sum += (u_int16_t)TCPSize;//加上TCP首部和数据部分的字节数
        
    
        memset(buf, 0x00, 2000);//初始化为0
        memcpy(buf, (u_int8_t *)((u_int8_t *)pIPHead + 20), TCPSize);//复制TCP首部和数据
      
        return CheckSum((u_int16_t*)buf, TCPSize, sum);//调用前面的函数
    }
    

    另注:以上代码是在VS2017上测试成功的,如果你拿去不能用,就看看哪里需要修改。

     

    展开全文
  • IP首部校验和计算与程序设计

    千次阅读 2020-11-25 09:49:08
    IP包的首部校验和的计算与程序设计一,感受与实验基本要求1.1 实验目的1.2 实验要求二,实验内容2.1 IP首部的基本校验方法2.2流程图2.3编程思路2.3.1得到数据并进行标准化2.3.2 信息合并后,把字符串转换成十进制,...

    一,感受与实验基本要求

    这是我《计算机网络》这门课程的第二个实验,说实话这个实验吧,我觉得我完成的不是特别的好,好些地方都是取巧,并不是真正意义上的完成这个实验。但是我觉得还是把这个实验的前后写下来,毕竟是见证自己的一个成长。接下来我会先介绍一下实验要求与实验内容。

    1.1 实验目的

    1.掌握IP协议包结构;
    2.学会IP协议包首部数据校验

    1.2 实验要求

    针对 IP 协议包结构,2 人一组,共同设计良好的人机界面,并实现首部校验和的计算程序。功能包括:
    (1)在界面上,用户能够输入或编辑 IP 协议包各字段数据,例如,“协议”字段应该是下拉选择 方式;
    (2)程序能够自动检查 IP 地址的合法性,且主机可用;
    (3)能够自动计算首部校验和的值,并显示计算结果;
    (4)必须验证程序的正确性:基于 Wireshark 工具所抓取的真实 IP 包首部数据,能够成功检验首 部校验和字段的计算程序。

    二,实验内容

    2.1 IP首部的基本校验方法

    1,把IP数据包的校验和字段置为0;   
    2,把首部看成以16位为单位的数字组成,依次进行二进制求和(注意:求和时应将最高位的进位保存,所以加法应采用32位加法);   
    3,将上述加法过程中产生的进位(最高位的进位)加到低16位(采用32位加法时,即为将高16位与低16位相加,之后还要把该次加法最高位产生的进位加到低16位)   
    4,将上述的和取反,即得到校验和。

    2.2流程图

    如图是流程图,可以先看看

    2.3编程思路

    2.3.1得到数据并进行标准化

    首先,程序需要从交互界面获取十进制表示的IP头除了校验和的各部分数据。将这些数据转换成16进制形式的字符串,进行标准化,若不进行标准化,则容易在不同信息合并中因为结束出现问题。

    String type1 = Edition.getSelectedItem();//获取所选内容
    			String HeadLength1 = HeadLength.getText();//获取文本框内的内容
    			String SeverType1 = SeverType.getSelectedItem();//下拉框的
    			SeverType1 = flags_change(SeverType1);
    			Sum[0] = Integer.parseInt(Connecting(type1,HeadLength1,SeverType1),16);//将版本,首部长度与服务结合,形成sum1。
    

    如上,采集下拉框Edition(版本)(使用getSelectedItem()函数)、SeverType(服务类型)与文本框HeadLength(头部长度)(使用getText()函数)的填入字符串,然后通过Connecting()函数将字符串拼接起来,并通过parseInt()内置函数将其转换成16进制存储在sum[]数组中。

      采集
    
    String S_IP1 = Length(encodeHEX(Integer.parseInt(S_IP_add1.getText())));
    
     标准化函数
    
    public static String Length(String a) {
       	String b = null;
       	if(a.length()==1) b = "0" + a;
       	else if(a.length() == 2) b = a;
       	return b;
       }
    

    是采集IP地址的第一个框的内容,而Length()的作用是标准化,将其表标准化为“xx”的形式,方便后面的拼接操作。

    2.3.2 信息合并后,把字符串转换成十进制,并存储在数组中。

    String AllLength2 = encodeHEX(Integer.parseInt(AllLength1));
    

    将两个IP的范围的16进制形式通过Connecting()函数连接,通过parseInt(String,16)转化成10进制的int型,并存储在数组Sum[]中。
    parseInt(String,16)的作用是把以字符串形式存储的16进制转换成10进制的整形。

    public String Connecting(String a,String b,String c) {//将首部连接
    		String d;
    		if(c != null) {
    			d = a+b+c;
    		}else {
    			d = a+b;
    		}
    		return d;
    	}
    

    看这个函数,可以决定是连接多少个首部,并存储在字符串中。

    2.3.3 进行求和运算。用循环方式对数组内的10进制进行求和,并转换成字符串形式的16进制。

    String SUM = count(Sum);
    

    这是对Sum数组进行求和运算,Sum是一个数组,里面存着首部除了校验和之外的全部信息的十进制形式。

    //先用10进制首部校验求和,然后转化成16进制
    	public static String count(int[]  a) {
    		int sum = 0;
    		String end;
    		for(int i = 0;i < 9;i++) {
    			sum += a[i];
    		}
    		end = encodeHEX(sum);
    		return end;
    	}
    

    为count()函数内部图,利用for循环将数组内部的10进制数字求和。这里返回的是和的16进制形式。

    2.3.4 判断是否产生溢出,若产生溢出,依次将最高位的数字加在低位上,直到满足4位的16进制。

    if(SUM.length()>4) {//若字长大于4位,则进行进位,将最高位加到最低位
    				String s = SUM.substring(SUM.length()-4);
    				String a = SUM.substring(0,1);
    				int i = Integer.parseInt(s,16);
    				int j = Integer.parseInt(a,16);
    				SUM = encodeHEX(i+j);
    			}
    

    若字长大于4位,则进行切片操取出最高位和后四位,然后换成10进制后相加并换成16进制。

    2.3.5 对进位后的和用ffff减去,所得的差即取反。

    下面展示一些 内联代码片

    //对16进制取反
    	public String qufan(String a) {
    		String m;
    		int i,j = 0xffff;
    		i = Integer.parseInt(a,16);
    		m = encodeHEX(j-i);
    		return m;
    	}
    

    如图,是进行取反的函数,将字符串a转换成10进制的整数后,用0xffff的10进制整数减去,再转换成16进制,即可得到去饭后的结果。此时整个运行结果结束。

    三,程序运行界面与结果

    3.1运行初始界面

    程序的初始界面
    在这里插入图片描述
    如图,因为一个IP地址不合法(>255),检测出后进行提示,提示重新输入。
    在这里插入图片描述
    如上图,因为IP地址不合法(输入中有字母),检测出后进行提示,提示重新输入。
    接下来我会简单介绍下判断是否合法是如何实现的。

    //判断输入的IP是否全为10进制
    	public boolean judge_ip(String a) {
    		boolean b = null != null;
    		for(int i=0 ; i<a.length() ; i++){
    		if(Character.isLetter(a.charAt(i))) b = true;//用char包装类中的判断字母的方法判断每一个字符
    		else b = false;
    		}
    		return b;
    	}
    	
    	//判断IP是否合法
    	public boolean Judge(String a) {
    		int b = Integer.parseInt(a);
    		if(b>=0&&b<=255) return true;
    		else return false;
    	}
    

    如上,是进行检验的两个函数,第一个函数judge_ip()作用是检验IP地址是否均为数字10进制,若检测到字符则返回true;而第二个函数比较简单,是接受字符串的数字,换成整形后判断范围,若在范围内则说明IP正确,返回true,反正不正确。两者均返回布尔值,通过布尔值判断。

    boolean judge1 = judge_ip(S_IP_add1.getText())||judge_ip(S_IP_add2.getText())||judge_ip(S_IP_add3.getText())||judge_ip(S_IP_add4.getText()||judge_ip(T_IP_add1.getText())||judge_ip(T_IP_add2.getText())||judge_ip(T_IP_add3.getText())||judge_ip(T_IP_add4.getText());
    			if(judge1 == true) JOptionPane.showMessageDialog(null, "地址输入不合法!请重新输入");
    

    如上,是进行是否均为10进制的判断。通过“或运算”,检查是否用10进制输入。因为judge_ip()函数是有字符就返回true,因此只需有一个true,则抛出提示,提示输入错误。

    boolean judge = Judge(S_IP_add1.getText())&&Judge(S_IP_add2.getText())&&Judge(S_IP_add3.getText())&&Judge(S_IP_add4.getText())&&Judge(T_IP_add1.getText())&&Judge(T_IP_add2.getText())&&Judge(T_IP_add3.getText())&&Judge(T_IP_add4.getText());
    			if(judge == false) JOptionPane.showMessageDialog(null, "地址输入不合法!请重新输入");
    

    如图,解释Judge()函数的用法,采用“与运算”。因为该函数在范围内为真,因此需要全部为true才可以通过。假若有一个为假,则judge1会返回false,抛出提示,提示输入错误。

    利用wireshark进行抓包,验证正确性

    在这里插入图片描述
    在这里插入图片描述
    可以看出,首部校验和码与wireshark抓包是符合的,因此可以说程序成功了。

    后言

    这次实验我还是比较高兴的,因为我独立完成了它,而且在这中间,我对Java的JFrame框架更熟练了。而且我也明白了IP包首部的数据所代表的意思。总的来说,通过这次实验,我在编程方面和就《计算机网络》的知识积累了一些,毕竟不积硅步,无以至千里。
    还有,这个程序其实有点问题,就是当求和比较大的时候,这个时候校验码会错误。
    在这里插入图片描述
    如图,就出现了错误,但我还没修好。也许以后会修修吧。
    各位大佬轻喷,我只是一个大三学生,而且在学校的学习中经常划水,要是哪里写的不好请多多斧正。

    程序原码

    package 计网实验;
    
    import java.awt.*;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import javax.swing.*;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JTextField;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    public class Frist_ extends JFrame{
    	JPanel jp1,jp2,jp3,jp4,jp5,jp6,jp7,jp8,jp9,jp10,jp11,jp12,jp13,jp14;
    	JLabel P_IP,F_length,S_Type,A_Length,Source_IP_add,Target_IP_add,sign,offset,ttl,mark,choose,Head_checksum;
    	JButton Calculation;
    	JTextField HeadLength,AllLength,S_IP_add1,S_IP_add2,S_IP_add3,S_IP_add4,T_IP_add1,T_IP_add2,T_IP_add3,T_IP_add4,Sign,Offset,TTL,Mark,Head_c;//SeverType;
    	Choice choosing,Edition,SeverType;
    	int[] Sum = new int[9];//各个码的10进制数存储在sum内
    	final Container c = getContentPane();//定义组件,并且为添加组件时使用
    	
    	void init() {
    		Calculation.addActionListener(new MyListener());;
    	}
    	//面板设计
    	public Frist_ () {
    		this.setTitle("IP包分析");
    		this.setSize(550, 300);
    		this.setResizable(false);//将窗口大小锁定
    		
    		jp1 = new JPanel();
    	    P_IP = new JLabel("版本:");
    		Edition = new Choice();
    		Edition.addItem("4");
    		Edition.addItem("6");
    		jp1.add(P_IP);
    	    jp1.add(Edition);
    	    jp1.setBounds(10,10,100,50);
    	    
    	    jp5 = new JPanel();
    	    F_length = new JLabel("首部长度:");
    	    HeadLength = new JTextField(5);
    	    jp5.add(F_length);
    	    jp5.add(HeadLength);
    	    jp5.setBounds(100, 10, 150, 50);
    	    
    	    jp6 = new JPanel();
    	    S_Type = new JLabel("服务类型:");
    	    SeverType = new Choice();
    	    SeverType.addItem("000");
    	    SeverType.addItem("001");
    	    SeverType.addItem("010");
    	    SeverType.addItem("011");
    	    SeverType.addItem("100");
    	    SeverType.addItem("101");
    	    SeverType.addItem("110");
    	    SeverType.addItem("111");
    	    //SeverType = new JTextField(5);
    	    jp6.add(S_Type);
    	    jp6.add(SeverType);
    	    jp6.setBounds(240,10, 150,50);
    	    
    	    jp7 = new JPanel();
    	    A_Length = new JLabel("总长度:");
    	    AllLength = new JTextField(5);
    	    jp7.add(A_Length);
    	    jp7.add(AllLength);
    	    jp7.setBounds(370,10,160,50);
    	    
    	    jp13 = new JPanel();
    	    mark = new JLabel("标识:");
    	    Mark = new JTextField(10);
    	    jp13.add(mark);
    	    jp13.add(Mark);
    	    jp13.setBounds(10,60,150, 50);
    	    
    	    jp10 = new JPanel();
    	    sign = new JLabel("标志:");
    	    Sign = new JTextField(3);
    	    jp10.add(sign);
    	    jp10.add(Sign);
    	    jp10.setBounds(150, 60, 100,50);
    	    
    	    jp11 = new JPanel();
    	    offset = new JLabel("偏位移:");
    	    Offset = new JTextField(3);
    	    jp11.add(offset);
    	    jp11.add(Offset);
    	    jp11.setBounds(250, 60, 100, 50);
    	    
    	    jp12 = new JPanel();
    	    ttl = new JLabel("生存时间:");
    	    TTL = new JTextField(3);
    	    jp12.add(ttl);
    	    jp12.add(TTL);
    	    jp12.setBounds(10,110,110, 50);
    	    
    	    jp2 = new JPanel();
    	    choose = new JLabel("协议:");
    	    choosing = new Choice();
    	    choosing.addItem("ICMP");
    	    choosing.addItem("IGMP");
    	    choosing.addItem("GGP");
    	    choosing.addItem("IP");
    	    choosing.addItem("TCP");
    	    choosing.addItem("EGP");
    	    choosing.addItem("UDP");
    	    choosing.addItem("IGRP");
    	    choosing.addItem("OSPF");
    	    jp2.add(choose);
    	    jp2.add(choosing);
    	    jp2.setBounds(100, 110, 130,50);
    	    
    	    jp14 = new JPanel();
    	    Head_checksum = new JLabel("首部校验和:");
    	    Head_c= new JTextField(5);
    	    Head_c.setEditable(false);
    	    jp14.add(Head_checksum);
    	    jp14.add(Head_c);
    	    jp14.setBounds(200,110, 200, 60);
    	    
    	    jp8 = new JPanel();
    	    Source_IP_add = new JLabel("源IP地址:");
    	    S_IP_add1 = new JTextField(3);
    	    S_IP_add2 = new JTextField(3);
    	    S_IP_add3 = new JTextField(3);
    	    S_IP_add4 = new JTextField(3);
    	    jp8.add(Source_IP_add);
    	    jp8.add(S_IP_add1);
    	    jp8.add(S_IP_add2);
    	    jp8.add(S_IP_add3);
    	    jp8.add(S_IP_add4);
    	    jp8.setBounds(10,160, 230,50);
    	    
    	    jp9 = new JPanel();
    	    Target_IP_add = new JLabel("目的IP地址");
    	    T_IP_add1 = new JTextField(3);
    	    T_IP_add2 = new JTextField(3);
    	    T_IP_add3 = new JTextField(3);
    	    T_IP_add4 = new JTextField(3);
    	    jp9.add(Target_IP_add);
    	    jp9.add(T_IP_add1);
    	    jp9.add(T_IP_add2);
    	    jp9.add(T_IP_add3);
    	    jp9.add(T_IP_add4);
    	    jp9.setBounds(10,210, 230,50);
    	    
    	    jp3 = new JPanel();
    	    Calculation = new JButton("计算首部校验和");
    	    jp3.add(Calculation);
    	    jp3.setBounds(290,180,110, 80);
    	    
    	   c.setLayout(null);//布局,为null方便进行自定义布局
    	   c.add(jp1);c.add(jp5);c.add(jp6);
    	   c.add(jp7);c.add(jp13);c.add(jp10);
    	   c.add(jp11);c.add(jp12);c.add(jp2);
    	   c.add(jp8);c.add(jp9);c.add(jp3);
    	   c.add(jp14);
    	   c.add(new JPanel());
    	   this.setVisible(true);
    	}
    	
    	class MyListener implements ActionListener{
    		public void actionPerformed(ActionEvent e) {
    			String type1 = Edition.getSelectedItem();//获取所选内容
    			String HeadLength1 = HeadLength.getText();//获取文本框内的内容
    			String SeverType1 = SeverType.getSelectedItem();//下拉框的
    			SeverType1 = flags_change(SeverType1);
    			Sum[0] = Integer.parseInt(Connecting(type1,HeadLength1,SeverType1),16);//将版本,首部长度与服务结合,形成sum1。
    			//String SeverType1 = SeverType.getText();//手动输入的
    			//Sum[0] = Integer.parseInt(Connecting(type1,HeadLength1,SeverType1),16);//将版本,首部长度与服务结合,形成sum1。(手动输入的)
    			String AllLength1 = AllLength.getText();
    			String AllLength2 = encodeHEX(Integer.parseInt(AllLength1));//读取总长度,并转换成字符串形式的16进制
    			Sum[1] = Integer.parseInt(AllLength2,16);
    			String Mark1 = Mark.getText();
    			String Mark2 = encodeHEX(Integer.parseInt(Mark1));//读取标识,并转换成字符串形式的16进制
    			Sum[2] = Integer.parseInt(Mark2,16);
    			String Sign1  = Sign.getText();
    			String Offset1 = Offset.getText();
    			Sum[3] = Integer.parseInt(Connecting(Sign1,Offset1,null),16);//将标志与偏位移连接			
    			String TTL1 = TTL.getText();
    			String TTL2 = encodeHEX(Integer.parseInt(TTL1));
    			String document1 = Choose(choosing.getSelectedItem());
    			Sum[4] = Integer.parseInt(Connecting(TTL2,document1,null),16);
    			boolean judge1 = judge_ip(S_IP_add1.getText())||judge_ip(S_IP_add2.getText())||judge_ip(S_IP_add3.getText())||judge_ip(S_IP_add4.getText())
                     	||judge_ip(T_IP_add1.getText())||judge_ip(T_IP_add2.getText())||judge_ip(T_IP_add3.getText())||judge_ip(T_IP_add4.getText());
    			if(judge1 == true) JOptionPane.showMessageDialog(null, "地址输入不合法!请重新输入");
    			String S_IP1 = Length(encodeHEX(Integer.parseInt(S_IP_add1.getText())));
    			String S_IP2 = Length(encodeHEX(Integer.parseInt(S_IP_add2.getText())));
    			String S_IP3 = Length(encodeHEX(Integer.parseInt(S_IP_add3.getText())));
    			String S_IP4 = Length(encodeHEX(Integer.parseInt(S_IP_add4.getText())));
    			String T_IP1 = Length(encodeHEX(Integer.parseInt(T_IP_add1.getText())));
    			String T_IP2 = Length(encodeHEX(Integer.parseInt(T_IP_add2.getText())));
    			String T_IP3 = Length(encodeHEX(Integer.parseInt(T_IP_add3.getText())));
    			String T_IP4 = Length(encodeHEX(Integer.parseInt(T_IP_add4.getText())));
    			//判断有没有不合法的输入
    			boolean judge = Judge(S_IP_add1.getText())&&Judge(S_IP_add2.getText())&&Judge(S_IP_add3.getText())&&Judge(S_IP_add4.getText())
    		                 	&&Judge(T_IP_add1.getText())&&Judge(T_IP_add2.getText())&&Judge(T_IP_add3.getText())&&Judge(T_IP_add4.getText());
    			if(judge == false) JOptionPane.showMessageDialog(null, "地址输入不合法!请重新输入");
    			Sum[5] = Integer.parseInt(Connecting(S_IP1,S_IP2,null),16);
    			Sum[6] = Integer.parseInt(Connecting(S_IP3,S_IP4,null),16);
    			Sum[7] = Integer.parseInt(Connecting(T_IP1,T_IP2,null),16);
    			Sum[8] = Integer.parseInt(Connecting(T_IP3,T_IP4,null),16);
    			String SUM = count(Sum);
    			if(SUM.length()>4) {//若字长大于4位,则进行进位,将最高位加到最低位
    				String s = SUM.substring(SUM.length()-4);
    				String a = SUM.substring(0,1);
    				int i = Integer.parseInt(s,16);
    				int j = Integer.parseInt(a,16);
    				SUM = encodeHEX(i+j);
    			}
    			SUM = qufan(SUM);
    			Head_c.setText("0x"+SUM);                                                                                                                                                                                                                                                                                                                                                                    
    		}
    	}
    	
    	//将首部连接
    	public String Connecting(String a,String b,String c) {
    		String d;
    		if(c != null) {
    			d = a+b+c;
    		}else {
    			d = a+b;
    		}
    		return d;
    	}
    	
    	//判断输入的IP是否全为10进制
    	public boolean judge_ip(String a) {
    		boolean b = null != null;
    		for(int i=0 ; i<a.length() ; i++){
    		if(Character.isLetter(a.charAt(i))) b = true;//用char包装类中的判断字母的方法判断每一个字符
    		else b = false;
    		}
    		return b;
    	}
    	
    	//判断IP是否合法
    	public boolean Judge(String a) {
    		int b = Integer.parseInt(a);
    		if(b>=0&&b<=255) return true;
    		else return false;
    	}
    	
    	//不同协议的不同数
    	public String Choose(String a) {
    		String b = null;
    		if(a.equals("ICMP" )) b = "01";
    		else if(a.equals("IGMP")) b = "02";
    		else if(a.equals("GGP")) b = "03";
    		else if(a.equals("IP")) b = "04";
    		else if(a.equals("TCP")) b = "06";
    		else if(a.equals("EGP")) b = "08";
    		else if(a.equals("UDP")) b = "17";
    		else if(a.equals("IGPR")) b = "88";
    		else if(a.equals("OSPF")) b = "89";
    		return b;
    	}
    	//不同标志不同的数
    	public String flags_change(String a) {
    		String b = null;
    		if(a.equals("000" )) b = "00";
    		else if(a.equals("001")) b = "01";
    		else if(a.equals("010")) b = "02";
    		else if(a.equals("011")) b = "03";
    		else if(a.equals("100")) b = "04";
    		else if(a.equals("101")) b = "05";
    		else if(a.equals("110")) b = "06";
    		else if(a.equals("111")) b = "07";
    		return b;
    		
    	}
    	
    	//将10进制转换成16进制
    	public static String encodeHEX(int numb) {   //注意,这里再写count函数时添加了一个静态,如果出现bug把静态删掉!!!
    		String hex= Integer.toHexString(numb);
    		return hex;
    	}
    	
    	//先用10进制首部校验求和,然后转化成16进制
    	public static String count(int[]  a) {
    		int sum = 0;
    		String end;
    		for(int i = 0;i < 9;i++) {
    			sum += a[i];
    		}
    		end = encodeHEX(sum);
    		return end;
    	}
    	
    	//特别的对IP进行补位运算,每个IP以4位为主,若小于2位,则进行补位
    	public static String Length(String a) {
    		String b = null;
    		if(a.length()==1) b = "0" + a;
    		else if(a.length() == 2) b = a;
    		return b;
    	}
    	
    	//对16进制取反
    	public String qufan(String a) {
    		String m;
    		int i,j = 0xffff;
    		i = Integer.parseInt(a,16);
    		m = encodeHEX(j-i);
    		return m;
    	}
    	
    	public static void main(String[] args) {
    		new Frist_().init();
    	}	
    }
    
    
    展开全文
  • IP首部有16bit的校验和,因此,IP首部以16bit为单位计算校验和IP首部的长度一定是16bit的整倍数,这是由于首部长字段是以32bit为单位计算的,不足的补0。 发送方计算方法: 1.首先把校验和的16bit置0。 2.将首部以...

    IP首部有16bit的校验和,因此,IP首部以16bit为单位计算校验和,IP首部的长度一定是16bit的整倍数,这是由于首部长字段是以32bit为单位计算的,不足的补0。

    发送方计算方法:
    1.首先把校验和的16bit置0。
    2.将首部以16bit为单位异或(或模2加,结果相同)。
    3.将异或结果取反,并填入校验和字段。

    接收方计算方法:
    1.将首部以16bit为单位异或(或模2加,结果相同)。
    2.异或结果如果所有位全为1,则无差错。

    例子:为计算方便,简化为以5位为单位计算校验和,校验和放在最后5位:
    1.发送方
    (1)首先把校验和的5bit置0:

    11010 10111 00000
    

    (2)将首部以16bit为单位异或(或模2加,结果相同):
    ①如果是异或:

    11010
    10111
    00000
    ------
    01101    // 结果
    

    ②如果是模2加,模2加为不带进位的二进制加法:

    11010
    10111
    00000
    ------
    01101    // 结果
    

    可见两种方法的结果相同。
    (3)将异或结果取反,并填入校验和字段:

    11010 10111 10010
    

    2.接收方
    (1)将首部以5bit为单位异或(或模2加,结果相同):

    11010
    10111
    10010
    -----
    11111    // 结果
    

    (2)可见结果位全为1,传输未出错。

    计算原理:
    一个二进制位与另一个二进制位的异或结果取反后的结果再和这两个二进制位异或,结果为1:

    0 xor 0 = 0; 
    ~0 = 1; 
    0 xor 0 xor 1 = 1;
    
    1 xor 1 = 0; 
    ~0 = 1; 
    1 xor 1 xor 1 = 1;
    
    0 xor 1 = 1; 
    ~1 = 0; 
    0 xor 1 xor 0 = 1;
    
    1 xor 0 = 1; 
    ~1 = 0; 
    1 xor 0 xor 0 = 1;
    

    而计算开始时,把首部校验和字段全置为0,而0与任何数异或都等于这个数本身,因此,发送端相当于把除首部校验和字段之外的值异或后取反并放在校验和字段,之后接收方计算时,相当于把求反后的值与原值计算校验和,每一位必定是1,否则就是出错(但全为1时不一定是正确的,false positive几率可忽略不计,但仍存在)。

    展开全文
  • 目录 ip首部校验和的计算方法(c语言实现)1. IP首部校验和的计算方法(C语言实现)2. 校验和计算方法3. 对校验和进行校验 ip首部校验和的计算方法(c语言实现) 1. IP首部校验和的计算方法(C语言实现) 关联博客:...
  • IP首部校验和计算原理

    千次阅读 2017-09-19 09:02:15
    以 IP 首部中的校验和为例,计算过程可分为三个步骤:   1.把校验和字段以全零填充; 2.对每 16 位(2 Byte)进行二进制反码求和; ...3.对得到的结果即为首部校验和。   示例: 对
  • java ip首部效验

    2020-12-07 20:31:32
    大学生网络实验课 (1)在界面上,用户能够输入或编辑IP协议包各字段数据,例如,“协议”字段应该是下拉选择 方式; (2)程序能够自动检查IP地址的合法性,且主机可用;...检验“首部校验和”字段的计算结果:
  • ip首部校验和计算

    千次阅读 2016-04-21 16:36:08
    IP首部校验和的计算方法:  1.把校验和字段清零。  2.然后对每16位(2字节)进行二进制反码求和,反码求和的意思是先对每16位求和,再将得到的和转为反码。  接下来详细描述反码求和的步骤:看下面的代码  算法:...
  • IP首部校验和算法

    2016-07-04 14:51:47
    IP首部校验和采用 的时反码求和算法。就是把首部看成16位的整数序列。然后反码求和。把 得到的值放入首部校验和位置。反码求和算法如下: 0和0相加是0但要产生一个进位1,0和1相加是1,1和1相加是0.若最高位相加...
  • IP首部校验和的计算

    万次阅读 2015-09-12 18:31:08
    IP首部校验和的计算
  • IP首部校验和计算

    千次阅读 2016-10-31 15:51:27
    首先将IP包头校验和字段置0 2.然后将整个IP包头每16bit 相加(相加结果如果有进位,则需将进位加到最低位,RFC1071有相关介绍) 3.最后将相加的结果取反即可unsigned short checksum(int nCount,unsigned short * ...
  • 由于在IP首部和ICMP报文中都存在着校验和的问题,在网上搜索了关于校验和的计算方法,得出如下的转载文章: i 将校验和字段置为0,然后将IP包头按16比特分成多个 校验和Header Checksum:0x618D将其重置为0X...
  • IP首部校验和的算法

    2016-06-06 16:53:38
    IP/ICMP/IGMP/TCP/UDP/等协议的校验和算法是相同的,采用的都是将数据流视为16位整数流进行重复的叠加计算。  计算校验和的步骤: (1)把校验和字段置为0。 (2)对IP头部的每16bit进行二进制求和。 (3)如果...
  • 目录 IP数据报首部校验和算法 详细 非代码 IP数据报首部校验和算法 详细 非代码 参考转载至: ​ http://www.cnblogs.com/fhefh/archive/2011/10/18/2216885.html 当用google搜索IP数...
  • IP数据报---首部校验和的计算方法

    千次阅读 多人点赞 2019-01-01 10:37:58
    为了方便大家,这里再借用网上的一个例子吧: ... 6E 06 00 00(校验字段)  DE B7 45 5D -&gt; 222.183.69.93 (源IP地址)  C0 A8 00 DC -&gt; 192.168.0.220 (目的IP地址...
  • IP数据报首部校验和算法

    千次阅读 2018-12-06 15:11:37
    看到一篇详细描述IP数据报首部校验和算法的文章,学习转载一下:  https://www.cnblogs.com/fhefh/archive/2011/10/18/2216885.html  
  • IP首部校验和的理解

    千次阅读 2010-06-28 23:28:00
    (转)对IP首部检验的理解 很多文章对ip首部检验的计算介绍得很简略,在理解上常常会比较困难。这篇文章是我自己的一些理解。或许也有不正确的地方,希望大家指正。 这个问题一直困绕了我很长时间,...
  • 简易的C语言IP和校验程序 输入01 输出01

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,980
精华内容 8,392
关键字:

ip首部校验和