python:并发编程(二十四)

news2024/10/6 16:23:26

前言

本文将和大家一起探讨python并发编程的实际项目:win图形界面应用(篇六,共八篇),系列文章将会从零开始构建项目,并逐渐完善项目,最终将项目打造成适用于高并发场景的应用。

本文为python并发编程的第二十四篇,上一篇文章地址如下:

python:并发编程(二十三)_Lion King的博客-CSDN博客

下一篇文章地址如下:

(暂无)
 

一、协议界面设计

1、TCP Client界面

设计 TCP Client 界面可以根据需求和设计风格进行定制。以下是一种简单的设计示例,用于展示 TCP Client 的基本元素和布局:

(1)标签和输入框:用于输入服务器的 IP 地址和端口号。

(2)连接按钮:单击该按钮将与服务器建立连接。

(3)发送区域:包含文本框和发送按钮,用于输入要发送给服务器的消息和发送消息的操作。

(4)接收区域:用于显示从服务器接收到的消息。

下面是一个示例代码,展示了如何创建一个简单的 TCP Client 界面:

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import socket
import threading

class TCPClientFrame(ttk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.create_widgets()

    def create_widgets(self):
        # IP 地址标签和输入框
        ip_label = ttk.Label(self, text="服务器 IP 地址:")
        ip_label.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        self.ip_entry = ttk.Entry(self)
        self.ip_entry.grid(row=0, column=1, padx=5, pady=5)

        # 端口号标签和输入框
        port_label = ttk.Label(self, text="服务器端口号:")
        port_label.grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
        self.port_entry = ttk.Entry(self)
        self.port_entry.grid(row=1, column=1, padx=5, pady=5)

        # 连接按钮
        connect_button = ttk.Button(self, text="连接", command=self.connect_to_server)
        connect_button.grid(row=2, column=0, columnspan=2, padx=5, pady=5)

        # 发送区域
        send_label = ttk.Label(self, text="发送消息:")
        send_label.grid(row=3, column=0, padx=5, pady=5, sticky=tk.W)
        self.send_entry = ttk.Entry(self)
        self.send_entry.grid(row=3, column=1, padx=5, pady=5)
        send_button = ttk.Button(self, text="发送", command=self.send_message)
        send_button.grid(row=4, column=0, columnspan=2, padx=5, pady=5)

        # 接收区域
        receive_label = ttk.Label(self, text="接收消息:")
        receive_label.grid(row=5, column=0, padx=5, pady=5, sticky=tk.W)
        self.receive_text = tk.Text(self, height=5, width=30)
        self.receive_text.grid(row=5, column=1, padx=5, pady=5)

        # 初始化 TCP 连接对象和接收线程
        self.tcp_client = None
        self.receive_thread = None

    def connect_to_server(self):
        # 获取服务器 IP 地址和端口号
        ip = self.ip_entry.get()
        port = int(self.port_entry.get())

        # 建立 TCP 连接
        try:
            self.tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp_client.connect((ip, port))
            messagebox.showinfo("连接成功", "成功连接到服务器")
            # 启动接收线程
            self.receive_thread = threading.Thread(target=self.receive_messages)
            self.receive_thread.start()
        except Exception as e:
            messagebox.showerror("连接错误", str(e))
            self.tcp_client = None

    def send_message(self):
        # 获取要发送的消息
        message = self.send_entry.get()

        # 发送消息给服务器
        try:
            self.tcp_client.send(message.encode())
            self.receive_text.insert(tk.END, f"发送消息: {message}\n")
        except Exception as e:
            messagebox.showerror("发送错误", str(e))

        # 清空发送输入框
        self.send_entry.delete(0, tk.END)

    def receive_messages(self):
        while True:
            try:
                # 接收服务器消息
                message = self.tcp_client.recv(1024).decode()
                self.receive_text.insert(tk.END, f"接收消息: {message}\n")
            except Exception as e:
                # 出现错误时关闭连接并退出接收线程
                self.tcp_client.close()
                messagebox.showinfo("连接断开", "与服务器的连接已断开")
                break

if __name__ == "__main__":
    app = tk.Tk()
    app.title("TCP Client")
    tcp_client_frame = TCPClientFrame(app)
    tcp_client_frame.pack()
    app.mainloop()

2、将TCPclient界面嵌入到主界面中

import tkinter as tk
from tkinter import ttk
import socket
import threading
from tkinter import messagebox

class TCPClientFrame(ttk.Frame):
    def __init__(self, parent):
        super().__init__(parent)
        self.create_widgets()

    def create_widgets(self):
        # IP 地址标签和输入框
        ip_label = ttk.Label(self, text="服务器 IP 地址:")
        ip_label.grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        self.ip_entry = ttk.Entry(self)
        self.ip_entry.grid(row=0, column=1, padx=5, pady=5)

        # 端口号标签和输入框
        port_label = ttk.Label(self, text="服务器端口号:")
        port_label.grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
        self.port_entry = ttk.Entry(self)
        self.port_entry.grid(row=1, column=1, padx=5, pady=5)

        # 连接按钮
        connect_button = ttk.Button(self, text="连接", command=self.connect_to_server)
        connect_button.grid(row=2, column=0, columnspan=2, padx=5, pady=5)

        # 发送区域
        send_label = ttk.Label(self, text="发送消息:")
        send_label.grid(row=3, column=0, padx=5, pady=5, sticky=tk.W)
        self.send_entry = ttk.Entry(self)
        self.send_entry.grid(row=3, column=1, padx=5, pady=5)
        send_button = ttk.Button(self, text="发送", command=self.send_message)
        send_button.grid(row=4, column=0, columnspan=2, padx=5, pady=5)

        # 接收区域
        receive_label = ttk.Label(self, text="接收消息:")
        receive_label.grid(row=5, column=0, padx=5, pady=5, sticky=tk.W)
        self.receive_text = tk.Text(self, height=5, width=30)
        self.receive_text.grid(row=5, column=1, padx=5, pady=5)

        # 初始化 TCP 连接对象和接收线程
        self.tcp_client = None
        self.receive_thread = None

    def connect_to_server(self):
        # 获取服务器 IP 地址和端口号
        ip = self.ip_entry.get()
        port = int(self.port_entry.get())

        # 建立 TCP 连接
        try:
            self.tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp_client.connect((ip, port))
            messagebox.showinfo("连接成功", "成功连接到服务器")
            # 启动接收线程
            self.receive_thread = threading.Thread(target=self.receive_messages)
            self.receive_thread.start()
        except Exception as e:
            messagebox.showerror("连接错误", str(e))
            self.tcp_client = None

    def send_message(self):
        # 获取要发送的消息
        message = self.send_entry.get()

        # 发送消息给服务器
        try:
            self.tcp_client.send(message.encode())
            self.receive_text.insert(tk.END, f"发送消息: {message}\n")
        except Exception as e:
            messagebox.showerror("发送错误", str(e))

        # 清空发送输入框
        self.send_entry.delete(0, tk.END)

    def receive_messages(self):
        while True:
            try:
                # 接收服务器消息
                message = self.tcp_client.recv(1024).decode()
                self.receive_text.insert(tk.END, f"接收消息: {message}\n")
            except Exception as e:
                # 出现错误时关闭连接并退出接收线程
                self.tcp_client.close()
                messagebox.showinfo("连接断开", "与服务器的连接已断开")
                break

class ProtocolTestApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("协议测试")
        self.geometry("400x300")

        self.notebook = ttk.Notebook(self)
        self.notebook.pack(fill="both", expand=True)

        self.create_menu()

    def create_menu(self):
        menu_bar = tk.Menu(self)

        # 创建客户端菜单和子菜单
        client_menu = tk.Menu(menu_bar, tearoff=0)
        client_menu.add_command(label="TCP Client", command=self.create_tcp_client_tab)
        client_menu.add_command(label="UDP Client", command=self.create_udp_client_tab)
        menu_bar.add_cascade(label="客户端", menu=client_menu)

        # 创建服务端菜单和子菜单
        server_menu = tk.Menu(menu_bar, tearoff=0)
        server_menu.add_command(label="TCP Server", command=self.create_tcp_server_tab)
        server_menu.add_command(label="UDP Server", command=self.create_udp_server_tab)
        menu_bar.add_cascade(label="服务端", menu=server_menu)

        # 将菜单栏配置到窗口
        self.config(menu=menu_bar)

    def create_tcp_client_tab(self):
        # 创建TCP Client的tab页
        tcp_client_frame = ttk.Frame(self.notebook)
        tcp_client_frame.pack(fill="both", expand=True)
        self.notebook.add(tcp_client_frame, text="TCP Client")

        # 创建关闭按钮
        close_button = ttk.Button(tcp_client_frame, text="×", width=8, command=lambda: self.close_tab(tcp_client_frame))
        close_button.place(relx=1.0, rely=0.0, anchor="ne")

        # 创建 TCP Client 的界面
        tcp_client = TCPClientFrame(tcp_client_frame)
        tcp_client.pack()

    def create_udp_client_tab(self):
        # 创建UDP Client的tab页
        udp_client_frame = ttk.Frame(self.notebook)
        udp_client_frame.pack(fill="both", expand=True)
        self.notebook.add(udp_client_frame, text="UDP Client")

        # 创建关闭按钮
        close_button = ttk.Button(udp_client_frame, text="×", width=8, command=lambda: self.close_tab(udp_client_frame))
        close_button.place(relx=1.0, rely=0.0, anchor="ne")

    def create_tcp_server_tab(self):
        # 创建TCP Server的tab页
        tcp_server_frame = ttk.Frame(self.notebook)
        tcp_server_frame.pack(fill="both", expand=True)
        self.notebook.add(tcp_server_frame, text="TCP Server")

        # 创建关闭按钮
        close_button = ttk.Button(tcp_server_frame, text="×", width=8, command=lambda: self.close_tab(tcp_server_frame))
        close_button.place(relx=1.0, rely=0.0, anchor="ne")

    def create_udp_server_tab(self):
        # 创建UDP Server的tab页
        udp_server_frame = ttk.Frame(self.notebook)
        udp_server_frame.pack(fill="both", expand=True)
        self.notebook.add(udp_server_frame, text="UDP Server")

        # 创建关闭按钮
        close_button = ttk.Button(udp_server_frame, text="×", width=8, command=lambda: self.close_tab(udp_server_frame))
        close_button.place(relx=1.0, rely=0.0, anchor="ne")

    def close_tab(self, frame):
        self.notebook.hide(frame)

if __name__ == "__main__":
    app = ProtocolTestApp()
    app.mainloop()

 

以上代码是在原有的 ProtocolTestApp 类的基础上进行了修改和扩展,主要实现了 TCP Client 界面的设计和功能。

ProtocolTestApp 类中,我们添加了一个新的方法 create_tcp_client_tab,用于创建 TCP Client 的选项卡。在该选项卡中,我们创建了一个 TCPClientFrame 对象,并将其添加到选项卡的 tcp_client_frame 中。

TCPClientFrame 是一个自定义的 tkinter Frame,用于显示 TCP Client 的界面和处理相关功能。在 TCPClientFrame 中,我们添加了一个 ttk.Entry 组件用于输入服务器的 IP 地址,一个 ttk.Button 组件用于连接服务器,一个 tkinter.Text 组件用于显示接收到的消息,以及一个 ttk.Entry 组件用于输入要发送的消息和一个 ttk.Button 组件用于发送消息。

在连接按钮的回调函数中,我们获取输入的 IP 地址并尝试与服务器建立连接。如果连接成功,我们创建一个新的线程来接收服务器发送的消息,并将其显示在接收文本框中。

发送按钮的回调函数中,我们获取输入的消息,并通过 TCP Client 的连接发送给服务器。

最后,通过修改 ProtocolTestApp 类的 create_tcp_client_tab 方法,将 TCPClientFrame 添加到 TCP Client 的选项卡中,从而实现了 TCP Client 界面的设计和功能。

整体而言,以上代码通过创建自定义的 TCPClientFrame 类和在选项卡中添加相应的组件,实现了 TCP Client 的界面设计和与服务器的连接、发送和接收消息的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/680007.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pandas进阶修炼120题-第二期(Pandas数据处理,21-50题)

文章目录 Pandas进阶修炼120题第二期 Pandas数据处理21.读取本地EXCEL数据22.查看df数据前5行23.将salary列数据转换为最大值与最小值的平均值方法一:正则表达式(分别使用apply(),applymap(),map()来实现)方法二:apply…

wifi芯片原理

一、在系统中的位置 基带(baseband) 基带的作用有三个: 1、队列包的管理 2、调试解调 3、CSMA/CA机制 CSMA/CA的全称是Carrier Sense Multiple Access with Collision Avoidance,即载波侦听多路访问/冲突避免。 各…

java——集合框架

文章目录 接口实现(类)算法1. 排序算法2. 查找算法3. 拷贝算法4. 填充算法5. 比较算法6. 随机算法7. 迭代器算法8. 交集、并集、差集9. 分割集合10. 数组和集合的互转 集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容&#x…

C++手撕红黑树

目录: 红黑树的概念红黑树的性质红黑树节点的定义 红黑树结构红黑树的插入操作红黑树的验证红黑树的代码实现 红黑树的删除红黑树与AVL树的比较红黑树的应用 总结 红黑树的概念 红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结…

DevOps系列文章之 Spring Boot Docker打包

应用准备容器化,因为几十个应用从测试到发布太麻烦了,而且还会因为环境的因素导致部署中出现各种问题。为了在开发、测试、生产都能保持一致的环境,就引进了容器技术,而目前常用的应用使用基于spring boot的。 在Spring Boot应用…

AI数字人之语音驱动面部模型及超分辨率重建Wav2Lip-HD

1 Wav2Lip-HD项目介绍 数字人打造中语音驱动人脸和超分辨率重建两种必备的模型,它们被用于实现数字人的语音和图像方面的功能。通过Wav2Lip-HD项目可以快速使用这两种模型,完成高清数字人形象的打造。 项目代码地址:github地址 1.1…

Canal监听MySQL

Canal监听MySQL 1、Mysql数据库开启binlog模式 注意:Mysql容器,此处Mysql版本为5.7 #进入容器 docker exec -it mysql /bin/bash #进入配置目录 cd /etc/mysql/mysql.conf.d #修改配置文件 vi mysqld.cnf(1) 修改mysqld.cnf配置文件,添加如…

Android:安卓开发使用okHttp进行网络请求和MySQL数据库完成图书馆管理系统APP

1、总体目标 1.1 项目概述 项目名称:基于安卓平台的图书管理系统。 本项目旨在研发一个图书管理系统,实现图书馆的信息化管理。在方便用户在线浏览,借阅,归还图书,方便图书馆管理员对图书进行管理。能很好的为用户提…

从零开始理解Linux中断架构(7)--- Linux执行上下文之中断上下文

1 中断处理程序的基本要求 当前运行的loop是一条执行流,中断程序运行开启了另外一条执行流,从上一节得知这是三种跳转的第三类,这个是一个大跳转。对中断程序的基本要求就是中断执行完毕后要恢复到原来执行的程序,除了时间流逝外,原来运行的程序应该毫无感知。 具体到Armv…

如何设计一个短信发送功能

本文主要分享了如何设计一个发送短信功能。 一、总结简述 1.梳理多个平台短信API的发送参数,集成封装提供统一的API,支持多个短信平台(阿里云、腾讯云、百度云、京东云、七牛云)灵活切换 2.提供存储方案,表结构设计…

Redis数据库操作

Redis 命令参考 — Redis 命令参考http://doc.redisfans.com/ 1、Redis,远程词典服务器,是一个基于内存的键值型NoSQL数据库 特征: 键值型,支持多种不同数据结构,功能丰富 单线程,每个命令具备原子性 …

C语言督学营(中级阶段)

文章目录 中级阶段9.数据结构概述逻辑结构 与 存储结构时间复杂度、空间复杂度 10.11.12.线性表 (代码实战)线性表的定义、特点1.线性表的顺序存储(顺序表示):顺序表静态分配动态分配顺序表的定义、初始化、插入、删除、按值查找、按位查找 操作 (代码):…

go开发多云资产管理平台

go开发多云资产管理平台cmdb 代码仓库github.com/yunixiangfeng/gocmdb 云主机管理 主机资源监控 开发流程 Welcome to Beego | Beego bee new gocmdb/servercd gocmdb/servergo mod tidygo get -u github.com/beego/beego/v2 go get -u "github.com/astaxie/beego/o…

津津乐道设计模式 - 模版模式详解(以女友化妆流程带你彻底明白)

🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Micro麦可乐的博客 🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战 🌺《RabbitMQ》…

JDBC-->java如何连接数据库(详细版小白必备)

个人名片: 🐅作者简介:一名大二在校生,热爱生活,爱好敲码! \ 💅个人主页 🥇:holy-wangle ➡系列内容: 🖼️ tkinter前端窗口界面创建与优化 &…

工业相机——显微镜头/放大镜头

校准尺,最小测量刻度为0.1mm 上图为手机拍的看不清,放了一个网上找的图,校准的详细参数见下图 例如:物距为116mm的显微镜头,这种镜头没有景深,只能测镜头前端到物体116mm的物体 ,几乎没有景深&a…

Vscode配置C/C++环境出现报错,导致不能运行代码,报错如下:

Vscode配置C/C环境出现报错,导致不能运行代码,报错如下: 问题描述—gcc : 无法将“gcc”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次…

Hexo博客搭建 —— Next主题配置

Hexo博客搭建 —— Next主题配置 文章目录 Hexo博客搭建 —— Next主题配置配置文件区分站点配置文件主题配置文件 配置文件描述简称引入next主题-sitenext主题页面模式设置-next设置首页不显示全文-site设置博客文章持久化连接-site下载插件URL Setting 参考文档 配置文件区分…

【Docker】一文了解DockerFile

文章目录 Dockerfile 概念DockerFile的指令1、FROM 指定基础镜像2、RUN 执行命令3、COPY 复制文件4、ADD 更高级的复制文件5、ENV 设置环境变量6、EXPOSE7、VOLUME 定义匿名卷8、CMD容器启动命令9、ENTRYPOINT入口点10、USER 指定当前用户11、WORKDIR 指定工作目录12、LABEL为镜…

网络安全、Web安全、渗透测试之笔经面经总结含答案

以下为网络安全各个方向涉及的面试题,星数越多代表问题出现的几率越大,祝各位都能找到满意的工作。 注:本套面试题,已整理成pdf文档,但内容还在持续更新中,因为无论如何都不可能覆盖所有的面试问题&#xf…