Python-web-communicate/main.py
2025-01-06 14:28:59 +08:00

103 lines
2.9 KiB
Python

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()