import tkinter as tk from tkinter import messagebox import socket import struct import re import time # 计算校验和 def calculate_checksum(data): checksum = 0 n = len(data) # 按 16 位块划分 for i in range(0, n - 1, 2): chunk = (data[i] << 8) + data[i + 1] checksum += chunk # 如果长度为奇数,补零 if n % 2 == 1: checksum += data[-1] << 8 # 将 32 位总和折叠为 16 位 checksum = (checksum >> 16) + (checksum & 0xFFFF) checksum += (checksum >> 16) # 对总和取反 return ~checksum & 0xFFFF # 构造 ICMP 报文 def construct_icmp(): # ICMP 报文头部: 类型(8), 代码(0), 校验和(0), 标识符(1), 序列号(1) icmp_header = struct.pack('!BBHHH', 8, 0, 0, 1, 1) data = b'Ping' # 计算校验和 checksum = calculate_checksum(icmp_header + data) # 填充校验和字段 icmp_header = struct.pack('!BBHHH', 8, 0, checksum, 1, 1) return icmp_header + data # 构造 UDP 报文 def construct_udp(src_port, dest_port): udp_header = struct.pack('!HHHH', src_port, dest_port, 8, 0) return udp_header # 验证输入 def validate_ip(ip): pattern = re.compile(r'^\d{1,3}(\.\d{1,3}){3}$') return pattern.match(ip) is not None # 发送报文 def send_packet(): try: target_ip = ip_entry.get() target_port = int(port_entry.get()) packet_type = var.get() if not validate_ip(target_ip): raise ValueError("目标 IP 地址无效") sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP if packet_type == "ICMP" else socket.IPPROTO_UDP) if packet_type == "ICMP": packet = construct_icmp() elif packet_type == "UDP": packet = construct_udp(12345, target_port) start_time = time.time() sock.sendto(packet, (target_ip, target_port)) end_time = time.time() result.set(f"报文发送成功!类型: {packet_type}, 往返时间: {end_time - start_time:.2f} 秒") except Exception as e: messagebox.showerror("错误", f"报文发送失败: {e}") # GUI 界面设计 window = tk.Tk() window.title("网络通信软件") tk.Label(window, text="目标 IP 地址:").grid(row=0, column=0) ip_entry = tk.Entry(window) ip_entry.grid(row=0, column=1) tk.Label(window, text="目标端口号:").grid(row=1, column=0) port_entry = tk.Entry(window) port_entry.grid(row=1, column=1) tk.Label(window, text="报文类型:").grid(row=2, column=0) var = tk.StringVar(value="ICMP") tk.Radiobutton(window, text="ICMP", variable=var, value="ICMP").grid(row=2, column=1) tk.Radiobutton(window, text="UDP", variable=var, value="UDP").grid(row=2, column=2) result = tk.StringVar() tk.Label(window, textvariable=result).grid(row=4, column=0, columnspan=3) tk.Button(window, text="发送报文", command=send_packet).grid(row=3, column=1) window.mainloop()