计算udp校验和例子_UDP校验和计算

The UDP header struct defined at /usr/include/netinet/udp.h is as follows

struct udphdr

{

u_int16_t source;

u_int16_t dest;

u_int16_t len;

u_int16_t check;

};

What value is stored in the check field of the header? How to verify if the checksum is correct? I meant on what data is the checksum computed? (Is it just the udp header or udp header plus the payload that follows it?)

Thanks.

解决方案

The UDP checksum is performed over the entire payload, and the other fields in the header, and some fields from the IP header. A pseudo-header is constructed from the IP header in order to perform the calculation (which is done over this pseudo-header, the UDP header and the payload). The reason the pseudo-header is included is to catch packets that have been routed to the wrong IP address.

Basically, at the receiving end, all the 16-bit words of the headers plus data area are added together (wrapping at 16 bits) and the result is checked against 0xffff.

On the sending side, it's a little more complex. A one's complement sum is performed on all the 16-bit values then the one's complement (i.e., invert all bits) is taken of that value to populate the checksum field (with the extra condition that a calculated checksum of zero will be changed into all one-bits).

The one's complement sum is not just the sum of all the one's complement values. It's a little more complex.

Basically, you have a running 16-bit accumulator starting at zero and you add every 16-bit value to that. Whenever one of those additions results in a carry, the value is wrapped around and you add one to the value again. This effectively takes the carry bit of the 16-bit addition and adds it to the value.

As an aside, and this is pure conjecture on my part but this could probably be efficiently done by use of the ADC (add with carry) instruction rather than ADD (surprisingly enough, add), or whatever equivalent instructions were available on your CPU at the time.

If there were no carry, ADC would just add the zero bit from the carry. In the days when this stuff was done (and yes, unfortunately, I am that old), memory was far more of a constraint than speed, not so much the case nowadays, so saving a few bytes in your code could well elevate you to the level of demi-god-emperor-of-the-universe :-)

Note that you never had to worry about carry the second time around (or a carry of two with the next ADC if you're using that method mentioned in the previous paragraph) since the two largest 16-bit values, when summed, produce (truncated from 0x1fffe) 0xfffe - adding one to that will never cause another carry.

Once the calculated one's complement sum is calculated, has its bits inverted and is inserted into the packet, that will cause the calculation at the receiving end to produce 0xffff, assuming no errors in transmission of course.

It's worth noting that the payload is always padded to ensure there's an integral number of 16-bit words. If it was padded, the length field tells you the actual length.

RFC768 is the specification which details this.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UDP校验和计算方法比较简单,下面是一个计算UDP校验和例子: ```python import socket import struct def checksum(data): # 如果数据长度为奇数,补一个字节的0 if len(data) % 2 != 0: data += b'\x00' # 将数据按每两个字节一组进行分组 words = struct.unpack('>' + 'H' * (len(data) // 2), data) # 将所有的16位的数相加 total = sum(words) # 将进位的16位加回到低16位 total = (total >> 16) + (total & 0xffff) # 取反得到校验和 checksum = (~total) & 0xffff return checksum # 构造UDP数据包 src_ip = '192.168.0.1' dst_ip = '192.168.0.2' src_port = 12345 dst_port = 54321 data = b'Hello, world!' # 构造UDP头部 udp_header = struct.pack('!HHHH', src_port, dst_port, len(data) + 8, 0x0000) # 计算校验和 pseudo_header = struct.pack('!4s4sBBH', socket.inet_aton(src_ip), socket.inet_aton(dst_ip), 0x00, socket.IPPROTO_UDP, len(udp_header) + len(data)) checksum_data = pseudo_header + udp_header + data udp_checksum = checksum(checksum_data) # 构造完整的UDP数据包 udp_packet = udp_header + struct.pack('!H', udp_checksum) + data # 打印UDP数据包的十六进制表示 print('UDP packet:', udp_packet.hex()) ``` 这个例子中,我们先构造了一个UDP数据包,然后计算了它的校验和计算校验和的过程分为以下几步: 1. 将数据按每两个字节一组进行分组。 2. 将所有的16位的数相加。 3. 将进位的16位加回到低16位。 4. 取反得到校验和。 需要注意的是,计算校验和时,需要先构造一个伪头部,伪头部中包含源IP地址、目的IP地址、协议号和UDP头部+数据的长度,然后将伪头部、UDP头部和数据拼接起来,计算校验和。这是因为UDP校验和不仅要校验UDP头部和数据,还要校验IP头部和UDP伪头部。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值