一、UDP/TCP头部信息

UDP校验和计算程序python udp校验和计算方法_TCP

  • 源端口号:发送方将UDP数据包通过源端口发送出去。
  • 目的端口号:接收方从目的端口号接收UDP数据包。
  • UDP长度:UDP头部长度(8字节)加上数据包的长度。
  • UDP校验和:用于UDP差错检测,确认从发送方到接收方传输的过程中,有没有比特位发生变化。

UDP校验和计算程序python udp校验和计算方法_UDP校验和计算程序python_02

  • 源端口:报文发送方应用程序对应的端口。
  • 目的端口:报文接收方应用程序对应的端口。
  • TCP序列号:32位的序列号标识了TCP报文中第一个字节在对应方向的传输中对应的字节序号。
  • TCP确认号:32位的确认号标识了报文发送端期望接收的字节序列。如果设置了ACK控制位,这个值表示一个准备接收的包的序列码。
  • TCP头部长度:表示TCP头的长度,单位是32比特(4字节),最大为15(60字节:头部20+选项40),也表示数据部分从何处开始。
  • 保留位:这些位必须是0,为了将来定义新的用途所保留。
  • 标志位:
    1、CWR(Congestion Window Reduce):拥塞窗口减少标志,由发送主机设置,用来表明它接收到了设置ECE标志的TCP包,发送端通过降低发送窗口的大小来降低发送速率。
    2、ECE(ECN Echo):ECN响应标志被用来在TCP3次握手时表明一个TCP端是具备ECN功能的,并且表明接收到的TCP包的IP头部的ECN被设置为11。
    3、URG(Urgent):该标志位置位表示紧急指针有效。该标志位目前已经很少使用。
    4、ACK(Acknowledgment):取值1代表确认序号字段有效,这是一个确认的TCP包,取值0则不是确认包。
    5、PSH(Push):该标志置位时,一般是表示发送端缓存中已经没有待发送的数据,接收端不用将该数据进行队列处理,而是尽可能快将数据转由应用程序处理。
    6、RST(Reset):用于复位相应的TCP连接。通常在发生异常或者错误的时候会触发复位TCP连接。
    7、SYN(Synchronize):序列号有效。该标志仅在三次握手建立TCP连接时有效。
    8、FIN(Finish):带有该标志置位的数据包用来结束一个TCP会话,但对应端口仍处于开放状态,准备接收后续数据。当FIN标志有效的时候我们称呼这个包为FIN包。
  • 窗口大小:用来标识确认序号之后还能接受多少字节的数据量,也表示接收端当前的接受窗口还剩多少空间,用于TCP的拥塞控制。
  • 校验和:发送端计算的校验和。
  • 紧急指针:紧急指针所指的位置往后部分为紧急数据,在URG标志位设置了才有效
  • TCP选项:长度不定,但长度必须是32位的整数倍。常见的选项包括MSS、SACK、Timestamp等。

二、UDP伪头部

UDP校验和计算程序python udp校验和计算方法_UDP_03

  • 源IP地址:发送方将UDP数据包通过源IP发送出去。
  • 目的IP地址:接收方从目的IP接收UDP数据包。
  • 协议类型:TCP为6,UDP为17。协议类型1字节,需要补充1字节长度。
  • UDP长度:UDP头部长度(8字节)加上数据包的长度。

三、UDP校验和计算

UDP校验和的需要计算UDP头部(计算的时候校验和部分的16位需要置0)加数据部分,还需要加上UDP伪头部。计算步骤如下:

  1. 将UDP伪头部、UDP头部和数据部分全部用16进制数表示。
  2. 将第一个16进制数与第二个16进制数相加,得到一个32位的数,如果32位数的高16位大于0,需要将高16位与低16位再相加,得到一个32位的数,直到高16位为0,得到这一次相加的结果。
  3. 将上一步得到的16位数与第三个数16进制的数相加,重复第二步,直到累加完所有的16进制数,并且得到的结果为16进制数。
  4. 将累加最后得到的16进制数取反,得到校验和。

四、计算方法

unsigned short check_sum(unsigned short *data, int num){
	unsigned long sum = 0;
	for(int i = 0;i < num; i++){
		sum += *data++;	//将2个16进制数相加
		sum = (sum>>16) + (sum&0xffff); //取相加结果的低16位与高16位相加
	}
	return ~sum;	//对最后的结果取反
}