我试图在Python中实现ping服务器,我将通过Pyping的源代码作为参考:https://github.com/Akhavi/pyping/blob/master/pyping/core.py
我无法理解为计算ICMP回应请求的校验和而实现的calculate_checksum函数。它的实施如下:
def calculate_checksum(source_string):
countTo = (int(len(source_string) / 2)) * 2
sum = 0
count = 0
# Handle bytes in pairs (decoding as short ints)
loByte = 0
hiByte = 0
while count < countTo:
if (sys.byteorder == "little"):
loByte = source_string[count]
hiByte = source_string[count + 1]
else:
loByte = source_string[count + 1]
hiByte = source_string[count]
sum = sum + (ord(hiByte) * 256 + ord(loByte))
count += 2
# Handle last byte if applicable (odd-number of bytes)
# Endianness should be irrelevant in this case
if countTo < len(source_string): # Check for odd length
loByte = source_string[len(source_string) - 1]
sum += ord(loByte)
sum &= 0xffffffff # Truncate sum to 32 bits (a variance from ping.c, which
# uses signed ints, but overflow is unlikely in ping)
sum = (sum >> 16) + (sum & 0xffff) # Add high 16 bits to low 16 bits
sum += (sum >> 16) # Add carry from above (if any)
answer = ~sum & 0xffff # Invert and truncate to 16 bits
answer = socket.htons(answer)
return answer
sum&= 0xffffffff用于将总和截断为32位。但是,额外的位(第33位)会发生什么。不应该作为一个附加物加入总和吗?此外,我无法理解此后的代码。
我阅读了RFC1071文档(http://www.faqs.org/rfcs/rfc1071.html),该文档解释了如何实现校验和,但我无法理解。
任何帮助,将不胜感激。谢谢!
我终于能够弄清楚calculate_checksum函数的工作情况,我试图在下面解释它。
校验和计算如下(根据RFC1071):
我们来举个例子吧。
如果要在八位字节序列[A,B,C,D,E]上计算校验和,则创建的对将是[A,B]和[C,D],其余的八位字节为E.对[ a,b]可以如下计算:
a * 256 + b其中a和b是八位字节
假如a是11001010且b是00010001,a * 256 + b = 1100101000010001,从而给出了八位组的连接结果。
因此,1的补数和计算如下:
sum = [A + B] +'[C + D] +'E其中+'表示1的补码加法
现在回到代码,行和&x 0xffffffff之前的所有内容计算我们之前计算的1的补码和。
我是&lt; 0&gt;
用于将总和截断为32位,尽管由于source_string的大小不是很大而在ping中不太可能超过总和
(source_string = header(8字节)+ payload(可变长度))。
am =(am >> 16)+(am&amp; fffffff)
这段代码是在总和大于16位的情况下实现的。总和分为两部分:
(sum >> 16):高阶16位
(sum&0xffff):低位16位
然后添加这两部分。最终结果可以是16位,而不是16位
我是+ =(I >> 16)
该行用于以前计算的结果总和超过16位并用于处理进位,类似于前一行。
最后,计算1的补码并截断为16位。 socket.htons()函数用于维护基于设备架构(Little endian和big endian)发送到网络的字节排列。