TCP/IP帧,校验的计算方式

1.IP报头的checksum

1.把校验和字段置为0;

2.对IP头部中的每16bit进行二进制求和;

3.如果和的高16bit不为0,则将和的高16bit和低16bit反复相加,直到和的高16bit为0,从而获得一个16bit的值;

4.将该16bit的值取反,存入校验和字段。

2.UDP/TCP报头的checksum

UDP/TCP报头中的校验和的计算比较复杂的,要用到 UDP/TCP伪首部:先要填充伪首部各个字段,然后再将UDP/TCP报头以后(包括报头)的数据附加到伪首部的后面,再对位首部使用上述校验和计算,所得到的值才是UDP/TCP报头部分的校验和。 位首部可以用如下的结构体表示:typedef struct{
 ULONG  sourceip;    //源IP地址
 ULONG  destip;      //目的IP地址
 BYTE mbz;           //置空(0)
 BYTE ptcl;          //协议类型
 USHORT plen;        //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度 单位:字节)
}Psd_Header; 注:1.对于UDP协议,如果不想计算的话,可以把校验和的两个字节置0,根据RFC的规定,这样上层UDP协议就不会计算校验和了2.sniffer查看校验和时,最好在中间节点。你在本机抓的时候,你的协议驱动在NDIS架构中层次太高,与标准协议栈是平级的,此时校验和处未被计算填充,还是垃圾填充数据。你在网络其它节点抓的时候,报文已经经过网卡的处理,校验和被正确设置了。

3.参考测试代码1

USHORT checksum(USHORT *buffer,int size)
{
 unsigned long cksum=0;
 while(size>1)
 {
  cksum+=*buffer++;
  size-=sizeof(USHORT);
 }
 if(size)
 {
  cksum+=*(UCHAR *)buffer;
 }
 //将32位数转换成16
 while (cksum>>16)
  cksum=(cksum>>16)+(cksum & 0xffff);
 return (USHORT) (~cksum);
}

4.参考测试代码2

#include "stm32f4xx.h"
#include "usart.h"
#include "delay.h"


#include <string.h>

#define LWIP_MAKE_U16(a, b) ((a << 8) | b) //((b << 8) | a)
#define LWIP_hton_U16(a)  ((((a)>>8)&0x00ff) |(((a)<<8)&0xff00))
#define LWIP_hton_U32(a) \
                         ((u32)((a>>0) & 0xff) << 24) | \
                         ((u32)((a>>8) & 0xff) << 16) | \
                         ((u32)((a>>16) & 0xff) << 8)  | \
                          (u32)((a>>24) & 0xff)
													
													
#define IP4_ADDR( a,b,c,d) \
                         ((u32)((a) & 0xff) << 24) | \
                         ((u32)((b) & 0xff) << 16) | \
                         ((u32)((c) & 0xff) << 8)  | \
                          (u32)((d) & 0xff)

#define FOLD_U32T(u)          (((u) >> 16) + ((u) & 0x0000ffffUL))
#define SWAP_BYTES_IN_WORD(w) (((w) & 0xff) << 8) | (((w) & 0xff00) >> 8)
u16 lwip_standard_chksum(void *dataptr, int len)
{
  u8 *pb = (u8 *)dataptr;
  u16 *ps, t = 0;
  u32 sum = 0;
  int odd = ((u32)pb & 1);

  /* Get aligned to u16_t */
  if (odd && len > 0) {
    ((u8 *)&t)[1] = *pb++;
    len--;
  }

  /* Add the bulk of the data */
  ps = (u16 *)(void *)pb;
  while (len > 1) {
    sum += *ps++;
    len -= 2;
  }

  /* Consume left-over byte, if any */
  if (len > 0) {
    ((u8 *)&t)[0] = *(u8 *)ps;
  }

  /* Add end bytes */
  sum += t;

  /* Fold 32-bit sum to 16 bits
     calling this twice is propably faster than if statements... */
  sum = FOLD_U32T(sum);
  sum = FOLD_U32T(sum);

  /* Swap if alignment was odd */
  if (odd) {
    sum = SWAP_BYTES_IN_WORD(sum);
  }

  return (u16)sum;
}

typedef struct udp_pcb {
	//IP
	u8 headIP;
	u8 priority;
	
  u16 lenIP;	
	u16 identifyflag;
	u16 flags ;
	
	u8 ttl;
	u8 proto;
	
	u16 checkIP;	
  u32 srcIP;
	u32 destIP;
	//UDP
	u16 srcPORT;
	u16 destPORT;	
	u16 lenUDP;	
	u16 checkUDP;
}udp_pcb_def;
udp_pcb_def udata;
void UDP_data(u8* retbuf,u16* retlen,u16 srcPort,u16 destPort,u8* srcIpbuf,u8* destIpbuf,u8 *dbuf,u16 dlen)
{		
	u32 chk_sum_IP = 0;
	u32 chk_sum_UDP = 0;
	u32 chk_sum = 0;
	u16 chk_sumxxx = 0;//测试
	
	u16 srcPORT = srcPort;
	u16 destPORT = destPort;
	
	u16 lenUDP = 8+dlen;
	u8 proto = 0x11;//udp
	
	u32 srcIP = IP4_ADDR(srcIpbuf[0],srcIpbuf[1],srcIpbuf[2],srcIpbuf[3]);//高低位对调
	u32 destIP = IP4_ADDR(destIpbuf[0],destIpbuf[1],destIpbuf[2],destIpbuf[3]);//高低位对调
	
	u8 * databuf = dbuf;
  u16 datalen = dlen;	
	
	
	u8 headIP = 0x45;//ipv4 20B
	u8 priority = 0x00;//优先级	
	
	u16 lenIP = 20+8+dlen;
	static u16 identifyflag = 0x0001;//++
	u16 flags = 0x0000;	
	u8 ttl = 0x40;//生命
	//~~~~~~~~~~~~~~~~~~~IP头
	chk_sum=0;
  chk_sumxxx = LWIP_MAKE_U16(headIP, priority);//0x4500
	chk_sum +=chk_sumxxx;
	
	chk_sumxxx = lenIP;
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = identifyflag;
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = flags;
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = LWIP_MAKE_U16(ttl, proto);//0x4011
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = (srcIP & 0xFFFF);
	chk_sum += chk_sumxxx;
	chk_sumxxx = (srcIP >> 16);
	chk_sum += chk_sumxxx;
	chk_sumxxx = (destIP & 0xFFFF);
	chk_sum += chk_sumxxx;
	chk_sumxxx = (destIP >> 16);
	chk_sum += chk_sumxxx;
	
	chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
	chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
	chk_sum = ~chk_sum;
	chk_sum_IP=chk_sum;	
	
	//~~~~~~~~~~~~~~~~~~~UDP头+data
	chk_sum=0;
	chk_sumxxx = (srcPORT);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = (destPORT);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = (lenUDP);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = lwip_standard_chksum(databuf, datalen);//求和完的结果会 高低位对调
	chk_sumxxx = SWAP_BYTES_IN_WORD(chk_sumxxx);
	chk_sum += chk_sumxxx;	
	//~~~~~~~~~~~~~~~~~~~伪UDP头
	chk_sumxxx = (srcIP & 0xFFFF);
	chk_sum += chk_sumxxx;
	chk_sumxxx = (srcIP >> 16);
	chk_sum += chk_sumxxx;
	chk_sumxxx = (destIP & 0xFFFF);
	chk_sum += chk_sumxxx;
	chk_sumxxx = (destIP >> 16);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = (lenUDP);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = (proto);
	chk_sum += chk_sumxxx;
	
	chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
	chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
	chk_sum = ~chk_sum;
	
	chk_sum_UDP=chk_sum;	
	//~~~~~~~~~~~~~~~~~~~整理数据
	//IP
	udata.headIP = headIP;
	udata.priority = priority;
	
  udata.lenIP = LWIP_hton_U16(lenIP);
	udata.identifyflag = LWIP_hton_U16(identifyflag);
	udata.flags = LWIP_hton_U16(flags);
	
	udata.ttl = ttl;
	udata.proto = proto;
	
	udata.checkIP = LWIP_hton_U16(chk_sum_IP);
  udata.srcIP = LWIP_hton_U32(srcIP);
	udata.destIP = LWIP_hton_U32(destIP);
	//UDP
	udata.srcPORT = LWIP_hton_U16(srcPORT);
	udata.destPORT = LWIP_hton_U16(destPORT);
	udata.lenUDP = LWIP_hton_U16(lenUDP);
	udata.checkUDP = LWIP_hton_U16(chk_sum_UDP);
	
	memcpy(&(retbuf[0]),(u8*)(&udata),sizeof(udp_pcb_def));
	//retbuf = (u8*)(&udata);
	//*retlen = sizeof(udp_pcb_def);
	return;	
}
	

int main(void)
{
	//IP_data();
	
	u8 ipsrcbuf[4];
	ipsrcbuf[0]=10;
	ipsrcbuf[1]=50;
	ipsrcbuf[2]=133;
	ipsrcbuf[3]=37;
	u8 ipdesbuf[4];
	ipdesbuf[0]=114;
	ipdesbuf[1]=55;
	ipdesbuf[2]=168;
	ipdesbuf[3]=54;
	
	u8 sdatabuf[] = "from minh";
	
	u8 retbuf[(sizeof(udp_pcb_def)+sizeof(sdatabuf))];
	u16 retlen=0;

	UDP_data(retbuf,&retlen,1501,1501,ipsrcbuf,ipdesbuf,sdatabuf,sizeof(sdatabuf)-1);
	
	memcpy(&(retbuf[sizeof(udp_pcb_def)]),sdatabuf,sizeof(sdatabuf)-1);
	
}
^DPPPI: 1,"10.50.143.226","0.0.0.0","219.150.32.132","123.150.150.150"
int i,n=0;
String[] words;
Scanner sc=new Scanner(System.in);
System.out.println ("请输入一串数字,以逗号隔开:");
	String str=sc.next();
	
	for(i=0;i<str.length();i++){
		if(str.charAt(i)==',') n++;
	}
	words=str.trim().split(",");
	for(i=0; i<str.length()-n; i++) {
		System.out.print(words[i]+"\t");
	}
/*
void IP_data(void){
	u32 chk_sum = 0;
	u16 chk_sumxxx = 0;
	
	u8 headIP1 = 0x45;//ipv4 20B
	u8 headIP2 = 0x00;//优先级
	
	u16 lenIP = 0x0026;
	u16 lenflag = 0x0001;//++
	u16 lenflagx = 0x0000;
	
	u8 ttl = 0x40;//生命
  u8 proto = 0x11;//udp
	
	u32 srcIP = 0x0a328525;//高低位对调
	u32 destIP = 0x7237a836;//高低位对调
	
	chk_sumxxx = LWIP_CHANGE_U16(LWIP_MAKE_U16(headIP1, headIP2));//0x4500
	chk_sum +=chk_sumxxx;
	
	chk_sumxxx = LWIP_CHANGE_U16(lenIP);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = LWIP_CHANGE_U16(lenflag);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = LWIP_CHANGE_U16(lenflagx);
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = LWIP_CHANGE_U16(LWIP_MAKE_U16(ttl, proto));//0x4011
	chk_sum += chk_sumxxx;
	
	chk_sumxxx = LWIP_CHANGE_U16(srcIP & 0xFFFF);
	chk_sum += chk_sumxxx;
	chk_sumxxx = LWIP_CHANGE_U16(srcIP >> 16);
	chk_sum += chk_sumxxx;
	chk_sumxxx = LWIP_CHANGE_U16(destIP & 0xFFFF);
	chk_sum += chk_sumxxx;
	chk_sumxxx = LWIP_CHANGE_U16(destIP >> 16);
	chk_sum += chk_sumxxx;
	
	//chk_sumxxx = (chk_sum >> 16);
	//chk_sum += chk_sumxxx;
	//chk_sumxxx = (chk_sum & 0xFFFF);
	//chk_sum += chk_sumxxx;
	
	chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
	chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
	chk_sum = ~chk_sum;
}
*/


 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值