import time from SimObjs import * from tkinter import * from tkinter import messagebox from PIL import ImageTk, Image from AgreementUtil import AgreementUtil def create_label(canvas: Canvas, x, y, width, height, text, rect_color, font_color, tag): canvas.create_rectangle(x, y, x + width, y + height, fill=rect_color, tags=tag) canvas.create_text(x + width / 2, y + height / 2, text=text, fill=font_color, tags=tag) return tag class PacketWindow(Toplevel): def __init__(self, master, packet, packet_step=["app", "trans", "ip", "mac"], *args, **kwargs): """ packet:{"packet": True, "mode": {"app": True, "trans": True, "ip": True, "mac": True}} """ super().__init__(master, *args, **kwargs) self.master = master self.width = 300 self.height = 400 self.geometry(f"{self.width}x{self.height}+200+200") self.attributes("-topmost", True) self.resizable(width=False, height=False) self.packet_button_str = {"app": "应用层", "ip": "网络层", "mac": "链路层", "trans": "传输层"} if not packet["packet"]: packet["mode"] = packet["mode"][::-1] # True 为封包 False 为解包 self.packet_step = packet_step self.step = 0 self.packet: dict[str: bool] = packet self.sendObj: SimHost = packet["sendObj"] self.receiveObj: SimHost = packet["receiveObj"] self.packet_option = {"app": {"color": "#ff3b26", "command": self.app_packet if packet["packet"] else self.app_unpack}, "ip": {"color": "#00a2f2", "command": self.ip_packet if packet["packet"] else self.ip_unpack}, "mac": {"color": "#46707a", "command": self.mac_packet if packet["packet"] else self.mac_unpack}, "trans": {"color": "#710a00", "command": self.trans_packet if packet["packet"] else self.trans_unpack}} self.canvas = Canvas(self, width=self.width, height=self.height) self.canvas.place(x=0, y=0, anchor='nw') self.packet_height, self.packet_init_width = 25, 100 self.background_img = ImageTk.PhotoImage(Image.open("../datas/images/背景@2x.png").resize((self.width, self.height))) self.canvas.create_image(0, 0, image=self.background_img, anchor=NW) # self.packet_rect = create_label(self.canvas, int(self.width / 2) - self.packet_init_width / 2, 10, width=self.packet_init_width, height=self.packet_height, text=self.packet["tag"], rect_color="#dee1e6", font_color="black", tag="packet") self.step_y = {} self.message = packet["tag"] self.create_widget() def move_to(self, tag, target_x, target_y, speed=10): # 获取当前位置 current_coords = self.canvas.coords(tag) if len(current_coords) < 2: return # 如果没有坐标,就退出函数 current_x, current_y = current_coords[0], current_coords[1] # 计算移动方向 delta_x = (target_x if target_x else current_x) - current_x delta_y = (target_y if target_y else current_y) - current_y # 计算下一步的位置 next_x = current_x + (speed if delta_x > 0 else -speed) if abs(delta_x) > speed else (target_x if target_x else current_x) next_y = current_y + (speed if delta_y > 0 else -speed) if abs(delta_y) > speed else (target_y if target_y else current_y) # 移动对象 self.canvas.move(tag, next_x - current_x, next_y - current_y) # 如果对象还没有到达目标,继续移动 if next_x != (target_x if target_x else current_x) or next_y != (target_y if target_y else current_y): self.canvas.after(10, lambda: self.move_to(tag, target_x, target_y, speed)) def create_widget(self): mode_text = "封包" if self.packet["packet"] else "解包" num, margin_top, button_width, button_height = 1, 30, 120, 40 for data in self.packet["mode"]: key = list(data.keys())[0] value = list(data.values())[0] if value: Button(self, text=self.packet_button_str[key] + mode_text, command=self.packet_option[key]["command"], font=("", 16)).place(x=40, y=30 + (margin_top + button_height) * (num - 1), width=button_width, height=button_height) # 动画 # self.canvas.create_rectangle(self.width - 80 - 40, 80 + (margin_top + 20 + button_height) * (num - 1), # self.width - 40, 80 + (margin_top + 20 + button_height) * (num - 1) + 25, fill=self.packet_option[key]["color"]) # self.canvas.create_text(self.width - 40 - 40, 80 + (margin_top + 20 + button_height) * (num - 1) + 12.5, # text=self.packet_button_str[key], font=("", 16), fill="white") # self.step_y[key] = 80 + (margin_top + 20 + button_height) * (num - 1) num += 1 Button(self, text="发送", command=self.send_packet, font=("", 16)).place(x=self.width - 60, y=self.height - 40, anchor=NW) Button(self, text="取消", command=self.destroy, font=("", 16)).place(x=self.width - 120, y=self.height - 40, anchor=NW) def send_packet(self): if self.step != len(self.packet_step): messagebox.showerror("注意", "尚未完成{}!".format("封包" if self.packet["packet"] else "解包")) return self.packet["send"](self.message) self.destroy() def create_window(self, option): toplevel = Toplevel(self) toplevel.title(option["title"]) toplevel.geometry("450x220+300+300") for entry_option in option["entry"]: index = option["entry"].index(entry_option) key = list(entry_option.keys())[0] value = list(entry_option.values())[0] Label(toplevel, text=key, font=("", 16)).grid(row=index, column=0, padx=20, pady=10) if value is None: continue Entry(toplevel, textvariable=value, font=("", 16), width=15).grid(row=index, column=1, pady=10) Button(toplevel, text="提交", command=option["command"], font=("", 16)).place(x=450 - 60, y=220 - 40, anchor=NW) Button(toplevel, text="取消", command=toplevel.destroy, font=("", 16)).place(x=450 - 120, y=220 - 40, anchor=NW) toplevel.attributes("-topmost", True) return toplevel def app_packet(self): """ 应用层封包 """ if self.packet_step[self.step] != "app": messagebox.showerror("注意", "封包顺序出错!") return SourceAppAddr = StringVar() TargetAppAddr = StringVar() def packet(): toplevel.destroy() source_app_addr = SourceAppAddr.get() target_app_addr = TargetAppAddr.get() if source_app_addr == self.sendObj.interface[0]["addr"] \ and target_app_addr == self.receiveObj.interface[0]["addr"]: # 动画 # app_rect = create_label(self.canvas, self.width / 2 + 200, int(self.step_y["app"]), 50, 25, "AH", "#ff3b26", "white", tag="app") # self.move_to(self.packet_rect, None, int(self.step_y["app"]), speed=1) # self.move_to(app_rect, self.width / 2 + self.packet_init_width / 2, int(self.step_y["app"]), speed=1) self.message = target_app_addr + "&" + self.packet["tag"] self.master.message.show_message("应用层封包成功!数据包如下: \n{}".format(self.message)) self.step += 1 else: messagebox.showerror("提示", "应用层地址填写有误,请仔细检查!") toplevel = self.create_window({"title": "应用层封包", "entry": [{"发送主机应用层地址:": SourceAppAddr}, {"接收主机应用层地址:": TargetAppAddr}], "command": packet}) def app_unpack(self): """ 应用层解包 """ if self.packet_step[self.step] != "app": messagebox.showerror("注意", "解包顺序出错!") return TargetAppAddr = StringVar() def packet(): toplevel.destroy() target_app_addr = TargetAppAddr.get() if target_app_addr == self.receiveObj.interface[0]["addr"]: self.message = self.message.split("&")[1] self.master.message.show_message("应用层解包成功!数据包如下: \n{}".format(self.message)) self.step += 1 else: messagebox.showerror("提示", "应用层地址填写有误,请仔细检查!") toplevel = self.create_window({"title": "应用层解包", "entry": [{"接收主机应用层地址:": TargetAppAddr}], "command": packet}) def trans_packet(self): """ 传输层封包 """ if self.packet_step[self.step] != "trans": messagebox.showerror("注意", "封包顺序出错!") return SentPort = StringVar() RcptPort = StringVar() SplitCount = IntVar() def packet(): sent_port = SentPort.get() rcpt_port = RcptPort.get() split_count = SplitCount.get() count = split_appdata(self.packet["size"]) print(sent_port, self.sendObj.interface[0]["conn_port"]) if sent_port == self.sendObj.interface[0]["conn_port"] \ and rcpt_port == self.receiveObj.interface[0]["conn_port"]\ and split_count == count: toplevel.destroy() # 动画 # self.canvas.delete(self.packet_rect) # self.canvas.delete("app") # self.packet_rect = create_label(self.canvas, int(self.width / 2) - self.packet_init_width / 2, int(self.step_y["app"]), # width=self.packet_init_width + 50, height=self.packet_height, # text="A-" + self.packet["tag"], rect_color="#dee1e6", font_color="black", # tag="packet") # trans_rect = create_label(self.canvas, self.width / 2 + 200, int(self.step_y["trans"]), 50, 25, "PH", "#ff3b26", # "white", tag="trans") # self.move_to(self.packet_rect, None, int(self.step_y["trans"]), speed=1) # self.move_to(trans_rect, self.width / 2 + self.packet_init_width / 2 + 50, int(self.step_y["trans"]), speed=1) self.message = AgreementUtil.create_udp_packet(self.message, int(sent_port), int(rcpt_port)) self.master.message.show_message("传输层封包成功!数据包如下:\n{}".format(str([str(i + 1) + "-" + str(self.message) for i in range(split_count)]))) self.step += 1 else: messagebox.showerror("提示", "传输层封包信息填写有误,请仔细检查!") toplevel = self.create_window({"title": "传输层封包", "entry": [{"发送主机端口:": SentPort}, {"接收主机端口:": RcptPort}, {"拆包数量": SplitCount}, {"每个包约2048": None}], "command": packet}) def trans_unpack(self): """ 传输层解包 """ print(self.packet_step) print(self.step) if self.packet_step[self.step] != "trans": messagebox.showerror("注意", "解包顺序出错!") return RcptPort = StringVar() def packet(): rcpt_port = RcptPort.get() if rcpt_port == self.receiveObj.interface[0]["conn_port"]: toplevel.destroy() data = AgreementUtil.parse_udp_packet(self.message) print(data) self.message = data[-1] self.master.message.show_message("传输层解包成功!数据包如下:\n{}".format(self.message)) self.step += 1 else: messagebox.showerror("提示", "传输层解包信息填写有误,请仔细检查!") toplevel = self.create_window({"title": "传输层解包", "entry": [{"接收主机端口:": RcptPort}], "command": packet}) def ip_packet(self): """ 网络层封包 """ if self.packet_step[self.step] != "ip": messagebox.showerror("注意", "封包顺序出错!") return SourceIP = StringVar() TargetIP = StringVar() def packet(): source_ip = SourceIP.get() target_ip = TargetIP.get() if source_ip == self.sendObj.interface[0]["ip"] \ and target_ip == self.receiveObj.interface[0]["ip"]: toplevel.destroy() self.message = AgreementUtil.create_ip_packet(self.message, source_ip, target_ip) self.master.message.show_message("网络层封包成功!数据包如下:\n{}".format(self.message)) self.step += 1 else: messagebox.showerror("提示", "网络层封包信息填写有误,请仔细检查!") toplevel = self.create_window({"title": "网络层封包", "entry": [{"发送主机IP:": SourceIP}, {"接收主机IP:": TargetIP}], "command": packet}) def ip_unpack(self): """ 网络层解包 """ print(self.packet_step) print(self.step) if self.packet_step[self.step] != "ip": messagebox.showerror("注意", "解包顺序出错!") return RcptIP = StringVar() def packet(): rcpt_ip = RcptIP.get() if rcpt_ip == self.receiveObj.interface[0]["ip"]: toplevel.destroy() data = AgreementUtil.parse_ip_packet(self.message) print(data) self.message = data[-1] self.master.message.show_message("网络层解包成功!数据包如下:\n{}".format(self.message)) self.step += 1 else: messagebox.showerror("提示", "网络层解包信息填写有误,请仔细检查!") toplevel = self.create_window({"title": "网络层解包", "entry": [{"接收主机IP:": RcptIP}], "command": packet}) def mac_packet(self): """ 链路层封包 """ if self.packet_step[self.step] != "mac": messagebox.showerror("注意", "封包顺序出错!") return SentMac = StringVar() RcptMac = StringVar() def packet(): sent_mac = SentMac.get() rcpt_mac = RcptMac.get() if sent_mac == self.sendObj.interface[0]["mac"] \ and rcpt_mac == self.receiveObj.interface[0]["mac"]: toplevel.destroy() self.message = AgreementUtil.create_ethernet_frame(self.message, sent_mac, rcpt_mac) self.master.message.show_message("链路层封包成功!数据包如下:\n{}".format(self.message)) self.step += 1 else: messagebox.showerror("提示", "链路层封包信息填写有误,请仔细检查!") toplevel = self.create_window({"title": "链路层封包", "entry": [{"发送主机MAC:": SentMac}, {"接收主机MAC:": RcptMac}], "command": packet}) def mac_unpack(self): """ 链路层解包 """ if self.packet_step[self.step] != "mac": messagebox.showerror("注意", "解包顺序出错!") return RcptMac = StringVar() def packet(): rcpt_mac = RcptMac.get() if rcpt_mac == self.receiveObj.interface[0]["mac"]: toplevel.destroy() data = AgreementUtil.parse_ethernet_frame(self.packet["tag"]) print(data) self.message = data[-1] self.master.message.show_message("链路层解包成功!数据包如下:\n{}".format(self.message)) self.step += 1 else: messagebox.showerror("提示", "链路层解包信息填写有误,请仔细检查!") toplevel = self.create_window({"title": "链路层解包", "entry": [{"接收主机MAC:": RcptMac}], "command": packet}) class AppData: def __init__(self, obj_id, id_key, app_pack_id, app_pack_size, app_pack_tag, source_app_addr, target_app_addr, app_packed_string, timestamp, canvas): self.obj_id = obj_id self.id_key = id_key self.app_pack_id = app_pack_id self.app_pack_size = app_pack_size self.app_pack_tag = app_pack_tag self.source_app_addr = source_app_addr self.target_app_addr = target_app_addr self.app_packed_string = app_packed_string self.timestamp = timestamp def pack(self): # 为了简化,我们打包成一个字典 return vars(self) @staticmethod def unpack(packed_data): # 解包为AppData对象 return AppData(**packed_data) class TransData: def __init__(self, obj_id, id_key, trans_pack_id, trans_seq, trans_tag, app_pack_id, sent_port, rcpt_port, source_app_addr, target_app_addr, trans_packed_string, timestamp): self.obj_id = obj_id self.id_key = id_key self.trans_pack_id = trans_pack_id self.trans_seq = trans_seq self.trans_tag = trans_tag self.app_pack_id = app_pack_id self.sent_port = sent_port self.rcpt_port = rcpt_port self.source_app_addr = source_app_addr self.target_app_addr = target_app_addr self.trans_packed_string = trans_packed_string self.timestamp = timestamp def pack(self): return vars(self) @staticmethod def unpack(packed_data): return TransData(**packed_data) class IPData: def __init__(self, obj_id, id_key, ip_pack_id, trans_pack_id, source_ip, target_ip, source_app_addr, target_app_addr, ip_packed_string): self.obj_id = obj_id self.id_key = id_key self.ip_pack_id = ip_pack_id self.trans_pack_id = trans_pack_id self.source_ip = source_ip self.target_ip = target_ip self.source_app_addr = source_app_addr self.target_app_addr = target_app_addr self.ip_packed_string = ip_packed_string def pack(self): return vars(self) @staticmethod def unpack(packed_data): return IPData(**packed_data) class MACData: def __init__(self, obj_id, id_key, mac_pack_id, ip_pack_id, sent_mac, rcpt_mac, source_ip, target_ip, source_app_addr, target_app_addr, mac_packed_string): self.obj_id = obj_id self.id_key = id_key self.mac_pack_id = mac_pack_id self.ip_pack_id = ip_pack_id self.sent_mac = sent_mac self.rcpt_mac = rcpt_mac self.source_ip = source_ip self.target_ip = target_ip self.source_app_addr = source_app_addr self.target_app_addr = target_app_addr self.mac_packed_string = mac_packed_string def pack(self): return vars(self) @staticmethod def unpack(packed_data): return MACData(**packed_data) def split_appdata(AppPackSize): MTU = 2048 return AppPackSize // MTU + (AppPackSize % MTU > 0) if __name__ == '__main__': # 假设的最大传输单元(MTU) MTU = 2048 # bytes # 模拟的数据和数据大小 SIMULATED_DATA = "hello" SIMULATED_SIZE = 2049 # 10 MB # 创建应用层数据包 app_packet = AppData("123", "123", "app1", SIMULATED_SIZE, "DATA", "192.0.2.1", "198.51.100.1", SIMULATED_DATA, time.time()) packed_app_data = app_packet.pack() print(packed_app_data)