Py 的魔力转圈圈:让我们一起用 Python3 & Tkinter 实现一个报文模拟器(附简单服务端代码)

一、引言

在工作中,我们总会遇到这样的需求:

我们需要向服务端程序发送指定格式的报文,然后服务端进行一定的处理之后,再向我们发回处理后的报文。

或者说,我们总会需要:

在编写服务端运行的程序的时候,总想要有一个能够模拟接收报文、监控报文并且还能够回复报文的一个客户端程序,这样就可以方便我们调试编写我们的服务端运行的程序逻辑。

前者是编写客户端程序的视角,后者是编写服务端程序的视角。

不管怎么说,我们总会想要一个报文模拟器,能够接收、监控、发送报文,可以方便我们客户端与服务端报文交互相关的开发测试工作。

我也一直有这么一个想法,正好最近遇到了一个报文格式相对比较复杂的项目,不自己编写一个报文模拟器的话,服务端程序的逻辑调试将会非常麻烦。

因此,我对这个报文模拟器提出了自己的需求:

  1. 可以接收服务端发来的报文信息
  2. 可以向服务端发送指定的报文信息
  3. 可以滚动监控报文的接收与发送
  4. 可以编辑报文保存到本地,也可以从本地读取报文
  5. 为了让这个项目自成一体,最好加上一个自行编写的简单的服务端程序

于是,经过了几天的鏖战,我终于算是非常简陋的实现了上述的需求:
1

那么,现在,就让我们一起来实现这个报文模拟器吧:)

ps: 对这个项目的代码感兴趣的同学,可以来我的 GitHub
wangying2016/Packet_Simulator

二、需求分析:选择 Python3 & Tkinter

既然要做一个报文模拟器,也给自己提出了引言中提到的 5 个需求,那么我们就需要思考如果去实现它。

1. 技术选择

技术上,这里我选择了 Python3 & Tkinter,至于为什么。。。

因为我喜欢 Python3 & Tkiner 呀 :)

不过话说回来,对于我们程序员来说,一些工作中的辅助工具,当然是编写难度越简单越好,编写代码量越少越好,选择的语言当是库越强大越好,其语言原生支持的 UI 库也能基本达到我们的需求即可。

于是乎,我选择了 Python3,另外又因为 Tkinter 是 Python3 原生支持的跨平台的 UI 库,其强大而又简单易学,因此实现的工具就这么决定下来了。

2. 业务选择

有些人可能会觉得奇怪,我们编写一个小工具,为什么还涉及到业务的选择呢?

这是当然的,尽管我们只是想要编写一个报文模拟器,但是我们需要构建一个简单的场景去让它跑起来。这个场景中,包括我们服务端的程序,包括我们需要去定义的服务端与客户端交互的报文格式,这些都是需要定义好的。

另外,我们将自己的业务定义的越简单越具有代表性,那么后续我们将这个报文模拟器移植到具体的项目中使用的时候,也好进行扩展,比如说服务端与客户端交互的报文格式,涉及到报文的加解密方式、报文的读取与写入等等逻辑,这些都是需要根据具体的项目进行个性化扩展的。

这里,我们简单定义以下的业务规则:

  1. 场景范围
    报文的发送使用短连接的方式进行,也就是每次发送完报文即关闭 socket 连接。另外,不论是服务端还是客户端,都需要保持一个长时间监听的 socket 连接,主要负责对对方发送的报文的监听。
  2. 报文格式
    报文的格式因项目而异,这里我们作为实验项目,定义最简单的就好了,这里我定义如下:
    2

我们做好了技术和业务上的选择,剩下来就是进行代码的编写了,从哪部分开始呢?

当然是 UI。

三、界面设计:强大而又简单的 Tkinter

在我的代码文件 Sim_Sender.py 中,类 GUI 是用来实现界面设计的关键的类。

其中的 __init__ 方法用来初始化界面布局,布局包括一个输入框、一个文本框、三个按钮以及一个滚动文本框。

另外,控件所绑定的触发函数也定义在 GUI 类中,还包括本地报文文件的读和写,以及按钮的触发函数、滚动文本框的内容的写入等等。

这里,我挑几个重药的地方解释一下吧。

1. 窗口建立与初始化

Tkinter 中的窗口建立是通过 Tk() 函数进行的,其返回的值类似于窗口句柄,可以进行窗口大小和位置的设定。

继承于 Frame(框架类)的 GUI 类是窗口布局的控制类,其中初始化了我们界面上显示的这种种的控件。

if __name__ == '__main__':
    ...
    # Gui
    root = Tk()
    app = GUI()
    ...
    root.geometry("350x600+300+300")
    root.mainloop()

代码中,在定义了窗口位置和大小之后,root.mainloop() 就是我们 Windows 编程中最熟悉的窗口消息循环啦:)

窗口的布局使用的是 pack 布局方式(Tkinter 支持 pack/grid/place 三种布局)。布局最核心的代码当然是 GUI 类中的 init_ui() 函数了:

    def init_ui(self):
        self.master.title("报文模拟器")
        self.pack(fill=BOTH, expand=True)

        self.frame1 = Frame(self)
        self.frame1.pack(fill=X, expand=True)

        lbl1 = Label(self.frame1, text="识别代码", width=10)
        lbl1.pack(side=LEFT, padx=5, pady=5)

        self.entry = Entry(self.frame1)
        self.entry.pack(fill=X, padx=5, expand=True)

        self.frame2 = Frame(self)
        self.frame2.pack(fill=X, expand=True)

        lbl2 = Label(self.frame2, text="报文内容", width=10)
        lbl2.pack(side=LEFT, anchor=N, padx=5, pady=5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值