用python+thinker模块实现 ping 程序,要求如下: 基本要求:理解 ping 工作原理,编程实现 ping 程序。 设计语言:Python 原理:发送 ICMP 的回送请求报文,接收 ICMP 报文,并分析该报文(可能收到差错报告报文,也可能正常收到 ICMP 回送回答报文)。 技术难点:构造 ICMP 回送请求报文并封装到 IP 数据报中,将该 IP 数据报发送出去并分析收到的结果,输出结果中一些统计信息的计算与呈现(图形化界面)。带有不同参数运行程序,其结果不同,即实现 windows 中 ping 命令部分选项功能,例如,发送 ICMP 报文数量、IP 中 TTL 设置等。
时间: 2024-02-11 11:09:45 浏览: 123
ping程序实现
好的,实现 ping 程序并加入 GUI 界面的话,我们可以使用 Python 的 tkinter 模块来完成。
首先,我们需要创建一个窗口,并在窗口中添加一些控件,如文本框、标签、按钮等。然后,我们需要在按钮的回调函数中调用 ping() 函数,并将结果输出到文本框中。此外,我们还需要在程序中加入相应的处理逻辑,根据用户的输入参数,设置 IP 数据报中的 TTL 等选项。
程序的大致流程如下:
```python
import socket
import struct
import time
import tkinter as tk
# 构造 ICMP 回送请求报文
def make_packet(id, seq):
header = struct.pack('bbHHh', 8, 0, 0, id, seq)
data = b'abcdefghijklmnopqrstuvwxyz'
packet = header + data
checksum = checksum(packet)
header = struct.pack('bbHHh', 8, 0, checksum, id, seq)
return header + data
# 计算校验和
def checksum(packet):
n = len(packet)
m = n % 2
s = 0
for i in range(0, n - m, 2):
s += (packet[i] << 8) + packet[i + 1]
if m:
s += packet[-1]
s = (s >> 16) + (s & 0xffff)
s += (s >> 16)
return ~s & 0xffff
# 发送 ICMP 请求报文,并接收响应报文
def ping(host, count=4, timeout=1, ttl=64):
try:
addr = socket.gethostbyname(host)
except:
return 'Ping request could not find host', host
result = ''
result += 'Pinging ' + addr + ' with ' + str(count) + ' bytes of data:\n'
for i in range(count):
# 构造 ICMP 请求报文
packet = make_packet(i, 0)
# 创建 socket 对象
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
# 设置 TTL
s.setsockopt(socket.IPPROTO_IP, socket.IP_TTL, ttl)
# 发送 ICMP 请求报文
start_time = time.time()
s.sendto(packet, (addr, 0))
# 接收 ICMP 响应报文
while True:
s.settimeout(timeout)
try:
data, address = s.recvfrom(1024)
except socket.timeout:
result += 'Request timed out.\n'
break
icmp_type, icmp_code, icmp_checksum, icmp_id, icmp_seq = struct.unpack('bbHHh', data[20:28])
if icmp_type == 0 and icmp_id == i:
# 计算延迟时间
end_time = time.time()
delay = (end_time - start_time) * 1000
result += 'Reply from ' + address[0] + ': bytes=32 time=' + str(round(delay, 2)) + 'ms\n'
break
s.close()
return result
# GUI 界面
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.pack()
self.create_widgets()
def create_widgets(self):
self.host_label = tk.Label(self, text='Host:')
self.host_label.grid(row=0, column=0)
self.host_entry = tk.Entry(self)
self.host_entry.grid(row=0, column=1)
self.count_label = tk.Label(self, text='Count:')
self.count_label.grid(row=1, column=0)
self.count_entry = tk.Entry(self)
self.count_entry.grid(row=1, column=1)
self.timeout_label = tk.Label(self, text='Timeout:')
self.timeout_label.grid(row=2, column=0)
self.timeout_entry = tk.Entry(self)
self.timeout_entry.grid(row=2, column=1)
self.ttl_label = tk.Label(self, text='TTL:')
self.ttl_label.grid(row=3, column=0)
self.ttl_entry = tk.Entry(self)
self.ttl_entry.grid(row=3, column=1)
self.result_text = tk.Text(self, width=40, height=10)
self.result_text.grid(row=4, column=0, columnspan=2)
self.ping_button = tk.Button(self, text='Ping', command=self.ping)
self.ping_button.grid(row=5, column=0)
def ping(self):
host = self.host_entry.get()
count = int(self.count_entry.get())
timeout = int(self.timeout_entry.get())
ttl = int(self.ttl_entry.get())
result = ping(host, count, timeout, ttl)
self.result_text.delete('1.0', tk.END)
self.result_text.insert(tk.END, result)
# 测试
if __name__ == '__main__':
root = tk.Tk()
app = Application(master=root)
app.mainloop()
```
这里实现了基本的 ping 功能,并加入了 GUI 界面,用户可以通过界面输入参数,然后点击“Ping”按钮,程序会调用 ping() 函数进行 ping 操作,并将结果输出到文本框中。如果收不到响应报文,则输出“Request timed out.”。
阅读全文