在/usr/include/netinet/udp.h中定义的UDP头结构如下
struct udphdr { u_int16_t source; u_int16_t dest; u_int16_t len; u_int16_t check; };
标题的检查字段中存储了什么值?如何验证校验和是否正确?我的意思是校验和计算的数据是什么?(它只是udp头或udp头加上它后面的有效负载吗?)
谢谢.
UDP校验和在整个有效负载和报头中的其他字段以及 IP报头中的一些字段上执行.从IP报头构造伪报头以便执行计算(通过该伪报头,UDP报头和有效载荷完成).包含伪报头的原因是捕获已路由到错误IP地址的数据包.
基本上,在接收端,标题的所有16位字加上数据区被加在一起(以16位包裹)并检查结果0xffff
.
在发送方面,它有点复杂.在所有16位值上执行一个补码和,然后从该值获取一个补码(即,反转所有位)以填充校验和字段(具有计算的校验和为零的额外条件将变为全部一个位).
一的补总和是不是所有的补值的简单相加.它有点复杂.
基本上,您有一个从零开始运行的16位累加器,并将每个16位值添加到该累加器.每当其中一个添加产生进位时,该值就会被包围,并再次向该值添加一个值.这有效地取得了16位加法的进位,并将其加到该值上.
顺便说一句,这对我来说是纯粹的猜想,但这可能通过使用
ADC
(with with carry)指令而不是ADD
(令人惊讶的是,添加)或者当时CPU上可用的任何等效指令来有效地完成. .如果没有进位,
ADC
只需从进位中添加零位.在这些东西完成的时候(是的,不幸的是,我已经很老了),内存远远超过了速度,而不是现在的情况,所以在你的代码中保存几个字节可以很好地提升你宇宙的半神 - 皇帝的水平:-)
请注意,您永远不必担心第二次携带(或者ADC
如果您使用前一段中提到的方法,则使用下一个携带两个)因为两个最大的16位值在求和时产生(截断)从0x1fffe
)0xfffe
- 添加一个将永远不会导致另一个携带.
一旦计算出计算出的一个补码和,就将其位反转并插入到数据包中,这将导致接收端的计算产生0xffff
,假设传输中没有错误.
值得注意的是,有效载荷总是被填充以确保存在整数个16位字.如果它被填充,长度字段告诉你的实际长度.
RFC768是详细说明的规范.