一、UDP/TCP头部信息
- 源端口号:发送方将UDP数据包通过源端口发送出去。
- 目的端口号:接收方从目的端口号接收UDP数据包。
- UDP长度:UDP头部长度(8字节)加上数据包的长度。
- UDP校验和:用于UDP差错检测,确认从发送方到接收方传输的过程中,有没有比特位发生变化。
- 源端口:报文发送方应用程序对应的端口。
- 目的端口:报文接收方应用程序对应的端口。
- 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伪头部
- 源IP地址:发送方将UDP数据包通过源IP发送出去。
- 目的IP地址:接收方从目的IP接收UDP数据包。
- 协议类型:TCP为6,UDP为17。协议类型1字节,需要补充1字节长度。
- UDP长度:UDP头部长度(8字节)加上数据包的长度。
三、UDP校验和计算
UDP校验和的需要计算UDP头部(计算的时候校验和部分的16位需要置0)加数据部分,还需要加上UDP伪头部。计算步骤如下:
- 将UDP伪头部、UDP头部和数据部分全部用16进制数表示。
- 将第一个16进制数与第二个16进制数相加,得到一个32位的数,如果32位数的高16位大于0,需要将高16位与低16位再相加,得到一个32位的数,直到高16位为0,得到这一次相加的结果。
- 将上一步得到的16位数与第三个数16进制的数相加,重复第二步,直到累加完所有的16进制数,并且得到的结果为16进制数。
- 将累加最后得到的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; //对最后的结果取反
}