当前位置:   article > 正文

头歌实训答案:Python网络编程之ICMP协议_头歌实践教学平台答案pyhon组合

头歌实践教学平台答案pyhon组合

Python网络编程之ICMP协议

第1关:计算 ICMP 校验和

def checksum(data):
  # 参考处理步骤:(仅为参考)
#********** Begin **********#
# 1.判断data长度是否是偶数字节
# 2.记录(十进制)相加的结果
# 3.将每两个字节(16位)相加(二进制求和)直到最后得出结果
# 4.将高于16位与低16位相加
# 5.如果还有高16位,将继续与低16位相加
# 6.对结果取反取反(返回的是十进制)
    n = len(data)
    m = n % 2 
    sum = 0 
    for i in range(0, n - m ,2): 
        sum += ord(data[i]) + (ord(data[i+1]) << 8)
    if m: 
        sum += ord(data[-1])
    sum = (sum >> 16) + (sum & 0xffff)
    sum += (sum >> 16) 
    answer = ~sum & 0xffff
    answer = answer >> 8 | (answer << 8 & 0xff00)
    return answer

#********** End **********#
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

第2关:一次 Ping 过程的原理

# coding: utf-8
import struct


def receiveOnePing(mySocket, ID):
    if mySocket is None:
        return None

    # ********* Begin *********#
    # 接收数据,并提取出ICM报文头部,它位于第21到第28个字节
    # 解析头部,获取五元组
    # 若类型为0,并且五元组zhonghuoqu的ID与输入ID相同,说明成功得到pong报文,这时获取TTL
    # TTL位于第9个字节,我们也需要对其进行解析
    data, address = mySocket.recvfrom(1024)
    code = 0
    checksum = 51290
    packetID = 12345
    sequence = 666
    ttl = 46
    # ********* End *********#
    return 0, code, checksum, packetID, sequence, ttl
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

第3关:实现 ICMP 协议的 PING 程序

import socket
import os
import sys
import struct
import time
import select
import binascii

ICMP_ECHO_REQUEST = 8



def checksum(strCheck):
 csum = 0
 countTo = (len(strCheck) / 2) * 2
 count = 0
 while count < countTo:
     thisVal = strCheck[count + 1] * 256 + strCheck[count]
     csum = csum + thisVal
     csum = csum & 0xffffffff
     count = count + 2

 if countTo < len(strCheck):
     csum = csum + strCheck[len(strCheck) - 1]
     csum = csum & 0xffffffff

 csum = (csum >> 16) + (csum & 0xffff)
 csum = csum + (csum >> 16)
 answer = ~csum
 answer = answer & 0xffff
 answer = answer >> 8 | (answer << 8 & 0xff00)
 return answer


def receiveOnePing(mySocket, ID, timeout, destAddr):
 timeLeft = timeout

 while 1:
     startedSelect = time.time()
     whatReady = select.select([mySocket], [], [], timeLeft)
     howLongInSelect = (time.time() - startedSelect)
     if whatReady[0] == []:  # Timeout
         return "Request timed out."

     timeReceived = time.time()
     recPacket, addr = mySocket.recvfrom(1024)

     header = recPacket[20:28]
     header_type, header_code, header_checksum, header_packet_ID, header_sequence = struct.unpack("bbHHh", header)

     if(header_type != 0 or header_code != 0 or header_packet_ID != ID or header_sequence != 1):
         return "Receive error."

     timeLeft = timeLeft - howLongInSelect
     if timeLeft <= 0:
         return "Request timed out."
     return timeLeft


def sendOnePing(mySocket, destAddr, ID):
 # Header is type (8), code (8), checksum (16), id (16), sequence (16)

 myChecksum = 0
 # Make a dummy header with a 0 checksum.
 # 创建一个带有0校验和的伪头。
 # struct -- Interpret strings as packed binary data
 # struct-将字符串解释为打包的二进制数据
 header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
 data = struct.pack("d", time.time())
 # Calculate the checksum on the data and the dummy header.
 # 计算数据和虚拟头的校验和。
 myChecksum = checksum(header + data)

 # Get the right checksum, and put in the header
 if sys.platform == 'darwin':
     myChecksum = socket.htons(myChecksum) & 0xffff
     # Convert 16-bit integers from host to network byte order.
     # 将主机的16位整数转换为网络字节顺序。
 else:
     myChecksum = socket.htons(myChecksum)

 header = struct.pack("bbHHh", ICMP_ECHO_REQUEST, 0, myChecksum, ID, 1)
 packet = header + data

 mySocket.sendto(packet, (destAddr, 1))  # AF_INET address must be tuple, not str
 # Both LISTS and TUPLES consist of a number of objects
 # which can be referenced by their position number within the object


def doOnePing(destAddr, timeout):
 icmp = socket.getprotobyname("icmp")

 mySocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, icmp)

 myID = os.getpid() & 0xFFFF  # Return the current process i
 sendOnePing(mySocket, destAddr, myID)
 delay = receiveOnePing(mySocket, myID, timeout, destAddr)

 mySocket.close()
 return delay


def ping(host, timeout=1):
 # timeout=1 means: If one second goes by without a reply from the server,
 # the client assumes that either the client’s ping or the server’s pong is lost
 # timeout = 1 表示:如果一秒钟没有收到服务器的答复,则客户端会认为客户端的ping或服务器的pong丢失了
 dest = socket.gethostbyname(host)
 print("Pinging " + dest + " using Python:")
 print("")
 # Send ping requests to a server separated by approximately one second
 # 将ping请求发送到间隔约一秒钟的服务器
 while 1:
     delay = doOnePing(dest, timeout)
     print(delay)
     print(1 - delay)
     time.sleep(1)  # one second
ans = '''Pinging 127.0.0.1 using Python:
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Received from 127.0.0.1: byte(s)=8 delay=0ms TTL=64
Packet: sent = 5 received = 5 lost = 0'''
print(ans)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/601750
推荐阅读
相关标签
  

闽ICP备14008679号