当前位置: 首页 > news >正文

使用Python简单实现客户端界面

服务端实现

import threading
import timeimport wx
from socket import socket, AF_INET, SOCK_STREAMclass LServer(wx.Frame):def __init__(self):wx.Frame.__init__(self, None, id=1002, title='L服务器端界面', pos=wx.DefaultPosition, size=(400, 450))# 窗口中添加面板pl = wx.Panel(self)# 创建一个盒子box = wx.BoxSizer(wx.VERTICAL)# 创建可伸缩的网格布局fgz1 = wx.FlexGridSizer(wx.HSCROLL)  # 水平方向布局# 创建按钮start_server_btn = wx.Button(pl, size=(133, 40), label='启动服务')record_btn = wx.Button(pl, size=(133, 40), label='保存记录')stop_server_btn = wx.Button(pl, size=(133, 40), label='停止服务')# 将按钮添加到网络布局中fgz1.Add(start_server_btn, 1, wx.TOP | wx.LEFT)fgz1.Add(record_btn, 1, wx.TOP | wx.CENTRE)fgz1.Add(stop_server_btn, 1, wx.TOP | wx.RIGHT)# 将可伸缩的网格布局添加到box中box.Add(fgz1, 1, wx.ALIGN_CENTRE)# 只读文本框,用于显示聊天内容self.show_text = wx.TextCtrl(pl, size=(400, 410), style=wx.TE_MULTILINE | wx.TE_READONLY)box.Add(self.show_text, 1, wx.ALIGN_CENTRE)# 把盒子放到面板中pl.SetSizer(box)'''-----------------------------以上代码为界面的绘制代码-----------------------------------''''''------------------------------设置服务器功能实现的必要属性----------------------------------'''self.isOn = False  # 存储服务器的启动状态,默认False没有启动# 服务器端绑定的IP地址和端口self.host_port = ('', 8888)  # 空的字符串代表的是本机的所有IP# 创建Socket对象self.server_socket = socket(AF_INET, SOCK_STREAM)# 绑定IP地址和端口self.server_socket.bind(self.host_port)# 监听self.server_socket.listen(5)# 创建一个字典,存储与客户端对话的会话线程self.session_thread_dict = {}  # key-value(客户端的名称key:绘画线程value)'''----------------------------------------------------------------'''# 当鼠标点击'启动服务'按钮时,需要执行的操作self.Bind(wx.EVT_BUTTON, self.start_server, start_server_btn)self.Bind(wx.EVT_BUTTON, self.save_record, record_btn)self.Bind(wx.EVT_BUTTON, self.stop_server, stop_server_btn)def stop_server(self,event):#print('服务器已停止服务')self.isOn=Falsedef save_record(self,event):#获取只读文本框的内容record_data=self.show_text.GetValue()with open('record.log','w',encoding='utf-8') as file:file.write(record_data)def start_server(self, event):# 判断服务器是否已经启动,只有服务器没有启动时菜启动if not self.isOn:  # 等监狱self.isOn==False# 启动服务self.isOn = True# 创建主线程对象,函数式创建主线程main_thread = threading.Thread(target=self.do_work)# 设置守护线程,父线程执行结束(窗口界面)子线程也自动关闭main_thread.daemon = True# 启动主线程main_thread.start()def do_work(self):while self.isOn:# 接收客户端的连接请求session_socket, client_addr = self.server_socket.accept()# 客户端发送连接请求后,发送过啊里的第一条数据为客户端名称,客户端的名称去作为字典中的键user_name = session_socket.recv(1024).decode('utf-8')# 创建一个会话线程对象session_thread = SessionThread(session_socket, user_name, self)# 存储到字典中self.session_thread_dict[user_name] = session_thread# 启动会话线程session_thread.start()# 输出服务器的提示信息self.show_info_and_send_client('服务器通知', f'欢迎{user_name}进入聊天室!',time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))# 当self.isOn的值为False时,执行关闭Socket对象self.server_socket.close()def show_info_and_send_client(self, data_source, data, data_time):# 字符串拼接操作send_data = f'{data_source}:{data}\n时间:{data_time}'# 只读文本框self.show_text.AppendText('-' * 40 + '\n' + send_data + '\n')# 每一个客户端都发送一次for client in self.session_thread_dict.values():# 判断当前的会话是否为开启状态if client.isOn:client.client_socket.send(send_data.encode('utf-8'))class SessionThread(threading.Thread):def __init__(self, client_socket, user_name, server):# 调用父类的初始化方法threading.Thread.__init__(self)self.client_socket = client_socketself.user_name = user_nameself.server = serverself.isOn = True  # 会话线程是否启动,当创建SessionThread对象是,会话线程就启动了,所以当前默认为True#def run(self):print(f'客户端:{self.user_name}已经与服务端建立连接.')while self.isOn:# 从客户端接收数据data = self.client_socket.recv(1024).decode('utf-8');# 如果客户端点击断开按钮,先给服务器发送断开连接,消息自定义 C-DISCONNECT-S 自定义结束词if data == 'C-DISCONNECT-S':self.isOn = False# 发送一条服务器通知# 其他聊天信息显示给所有客户端,包含服务器显示self.server.show_info_and_send_client('服务器通知', f'{self.user_name}离开了聊天室',time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))else:# 其他聊天信息显示给所有客户端,包含服务器显示self.server.show_info_and_send_client(self.user_name, data,time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))# 关闭socketself.client_socket.close()if __name__ == '__main__':# 初始化App()app = wx.App()# 创建自己的客户端界面对象client = LServer()client.Show()  # 可以改成LServer().Show()# 循环刷新显示app.MainLoop()

客户端实现

# coding:utf-8
import threadingimport wx
from socket import socket, AF_INET, SOCK_STREAMclass LClinet(wx.Frame):def __init__(self, clent_name):# 调用父类的初始化方法# None:没有父级窗口# id:表示当前窗口的一个编号# title:窗口标题# pos:窗体的打开位置# size:窗体的大小;单位是像素,400宽,450高wx.Frame.__init__(self, None, id=1001, title=clent_name + '的客户端界面', pos=wx.DefaultPosition,size=(400, 600))# 创建面板对象pl = wx.Panel(self)# 在面板中放上盒子box = wx.BoxSizer(wx.VERTICAL)  # 垂直方向布局# 可伸缩的网格布局fgz1 = wx.FlexGridSizer(wx.HSCROLL)  # 水平方向布局# 创建连个按钮connect_btn = wx.Button(pl, size=(200, 40), label='连接')disconnect_btn = wx.Button(pl, size=(200, 40), label='断开')# 把两个按钮放到可伸缩的网格布局fgz1.Add(connect_btn, 1, wx.TOP | wx.LEFT)fgz1.Add(disconnect_btn, 1, wx.TOP | wx.RIGHT)# 可伸缩的网格布局添加到box中box.Add(fgz1, 1, wx.ALIGN_CENTRE)# 只读文本框,用于显示聊天内容self.show_text = wx.TextCtrl(pl, size=(400, 210), style=wx.TE_MULTILINE | wx.TE_READONLY)box.Add(self.show_text, 1, wx.ALIGN_CENTRE)# 创建聊天内容的文本框self.chat_text = wx.TextCtrl(pl, size=(400, 210), style=wx.TE_MULTILINE)box.Add(self.chat_text, 1, wx.ALIGN_CENTRE)# 可伸缩的网格布局fgz2 = wx.FlexGridSizer(wx.HSCROLL)  # 水平方向布局# 创建连个按钮reset_btn = wx.Button(pl, size=(200, 40), label='重置')send_btn = wx.Button(pl, size=(200, 40), label='发送')# 把两个按钮放到可伸缩的网格布局fgz2.Add(reset_btn, 1, wx.TOP | wx.LEFT)fgz2.Add(send_btn, 1, wx.TOP | wx.LEFT)# 可伸缩的网格布局添加到box中box.Add(fgz2, 1, wx.ALIGN_CENTRE)# 将盒子放到面板中pl.SetSizer(box)'''------------------以上代码时客户端界面的绘制---------------------'''self.Bind(wx.EVT_BUTTON, self.connect_to_server, connect_btn)# 实例属性设置self.client_name = clent_nameself.isConnected = False  # 存储客户端连接服务器的状态,默认False未连接self.client_socket = None  # 设置客户端的socket对象为空self.Bind(wx.EVT_BUTTON, self.send_to_server, send_btn)self.Bind(wx.EVT_BUTTON, self.disconnect_to_server, disconnect_btn)self.Bind(wx.EVT_BUTTON, self.reset, reset_btn)def reset(self,event):# 清空文本框self.chat_text.SetValue('')def disconnect_to_server(self,event):#发送断开的信息self.client_socket.send('C-DISCONNECT-S'.encode('utf-8'))# 改变连接状态self.isConnected=Falsedef send_to_server(self, event):# 判断连接状态if self.isConnected:# 从可写文本框中获取输入的内容input_data = self.chat_text.GetValue()if input_data != '':# 向服务器发送数据self.client_socket.send(input_data.encode('utf-8'))# 发送完数据后清空文本框self.chat_text.SetValue('')def connect_to_server(self, event):print(f'客户端{self.client_name}连接服务器成功')# 如果客户端没有连接服务器,则开始连接if not self.isConnected:  # 等价与self.isConnected==False# TCP编程步骤server_host_port = ('127.0.0.1', 8888)# 创建socket对象self.client_socket = socket(AF_INET, SOCK_STREAM)# 发送连接请求self.client_socket.connect(server_host_port)# 只要连接成功,发送一条数据self.client_socket.send(self.client_name.encode('utf-8'))# 启动一个线程,客户端的线程与服务器的会话线程进行会话client_thread = threading.Thread(target=self.recv_data)# 设置线程守护,窗体关闭后,子线程也关闭client_thread.daemon = True# 修改连接状态self.isConnected = True# 启动线程client_thread.start()def recv_data(self):# 判断是否是连接状态while self.isConnected:# 接收服务器的数据data = self.client_socket.recv(1024).decode('utf-8')# 显示到文本框中self.show_text.AppendText('-' * 40 + '\n' + data + '\n')if __name__ == '__main__':# 初始化App()app = wx.App()name = input('请输入客户端名称:')# 创建自己的客户端界面对象client = LClinet(name)client.Show()  # 可以改成LClinet('LL').Show()# 循环刷新显示app.MainLoop()

相关文章:

使用Python简单实现客户端界面

服务端实现 import threading import timeimport wx from socket import socket, AF_INET, SOCK_STREAMclass LServer(wx.Frame):def __init__(self):wx.Frame.__init__(self, None, id1002, titleL服务器端界面, poswx.DefaultPosition, size(400, 450))# 窗口中添加面板pl …...

15分钟学 Go 第 43 天:前端与Go的结合

第43天:前端与Go的结合 目标:了解Go如何与前端交互,前端使用Vue.js 在现代Web开发中,Go语言常用于后端开发,而Vue.js是一个流行的前端框架,用于构建用户界面。结合二者,可以构建高效、可维护的…...

解决SRS推送webrtc流卡顿问题

目录 1.问题描述2.原因分析3.ffmpeg去掉B帧的方法3.1 命令行推流3.2 ffmpeg源码推流 1.问题描述 使用ffmpeg通过rtmp协议推流给SRS,然后浏览器通过webrtc拉取播放流,经多次测试发现webrtc播放流总是卡顿,而拉取rtmp流是正常的。 2.原因分析…...

GDPU Andriod移动应用 Broadcast Receiver

聆听广播,跟着节拍吧。 计时器 新建一个名为PhoneStateMonitor的工程; 实现一个应用运行时长的计时器,并在界面上刷新计数器,要求包括: (1)在Layout中包含两个TextView控件,横向分…...

CSP/信奥赛C++刷题训练:经典例题 - 栈(1):洛谷P3056 :[USACO12NOV] Clumsy Cows S

CSP/信奥赛C刷题训练:经典例题 - 栈(1):洛谷P3056 :[USACO12NOV] Clumsy Cows S 题目描述 Bessie the cow is trying to type a balanced string of parentheses into her new laptop, but she is sufficiently clums…...

WiFi一直获取不到IP地址是怎么回事?

在当今这个信息化时代,WiFi已成为我们日常生活中不可或缺的一部分。无论是家庭、办公室还是公共场所,WiFi都为我们提供了便捷的无线互联网接入。然而,有时我们可能会遇到WiFi连接后无法获取IP地址的问题,这不仅影响了我们的网络使…...

蓝牙BLE开发——iOS 每次写入数据超过200字节报错?

iOS 写入数据超过200字节报错 文章目录 iOS 写入数据超过200字节报错官方建议:报错问题解决 writeblecharacteristicvalue 官方建议: 并行调用多次会存在写失败的可能性。APP不会对写入数据包大小做限制,但系统与蓝牙设备会限制蓝牙4.0单次…...

Ascend Extension for PyTorch是个what?

1 Ascend Extension for PyTorch Ascend Extension for PyTorch 插件是基于昇腾的深度学习适配框架,使昇腾NPU可以支持PyTorch框架,为PyTorch框架的使用者提供昇腾AI处理器的超强算力。 项目源码地址请参见Ascend/Pytorch。 昇腾为基于昇腾处理器和软…...

学习docker第五弹-----高级篇start-Dockerfile

docker目录 1 Dockerfile是什么2 Dockerfile能干嘛3 如何书写Dockerfile3.1 Dockerfile构建过程解析3.2 小总结3.3 Dockerfile的基本知识3.5 保留字FROMMAINTAINERRUN 有两种方式EXPOSEWORKDIRENVUSERVOLUMEADDCMDENTRYPOINT 4 后记 1 Dockerfile是什么 Dockerfile顾名思义就是…...

【Elasticsearch】Elasticsearch集成Spring Boot

Elasticsearch集成Spring Boot 概述 Spring Data Elasticsearch 介绍一、环境初始化二、实战入门1、定义数据实体类2、定义Dao层3、框架集成-SpringData-集成测试-索引操作4、框架集成-SpringData-集成测试-文档操作5、框架集成-SpringData-集成测试-文档搜索 概述 Spring Data…...

HarmonyOS 移

什么是HarmonyOS HarmonyOS 中文名字是 鸿蒙操作系统 中国神话传说盘古在昆仑山开天辟地之前,世界是一团混沌状的元气,这种自然的元气叫做鸿蒙,那个时代成为鸿蒙时代华为公司的操作系统以鸿蒙取名,是不是有开天辟地之寓意&#x…...

跨子网的WinCC客户机/服务器如何实现通讯?

为了更有效地利用有限的IP地址,为了减少广播对网络带宽的占用从而提高带宽,为了实现在不同子网中应用不同的安全策略从而提高网络安全性,现场通常要求划分子网,将安全等级要求不同的计算机安置在不同的子网中,分开管理…...

java 面向对象高级

1.final关键字 class Demo{public static void main(String[] args) {final int[] anew int[]{1,2,3};// anew int[]{4,5,6}; 报错a[0]5;//可以,解释了final修饰引用性变量,变量存储的地址不能被改变,但地址所指向的对象的内容可以改变} }什…...

递推经典例题 - 爬楼梯

一、题目阅读 题目描述 一段楼梯有n级台阶。你每次可以跨一个、两个或者三个台阶。 请问走上n级台阶有几种方案?答案对998244353取模。 输入格式 一行一个数n。 输出格式 一行一个数,表示方案数。 样例 Input 1 3 Output 1 4 样例解释 1 1 1 3 1 2 …...

OpenCV视觉分析之目标跟踪(12)找到局部的最大值函数meanShift()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在反向投影图像上找到一个对象。 meanShift 是一种用于图像处理和计算机视觉领域的算法,特别适用于目标跟踪、图像分割等任务。该算…...

《数据治理精选案例集2.0(2024版)》592页PDF(已授权分享)

《亿信华辰数据治理精选案例集2.0》是北京亿信华辰软件有限责任公司倾力打造的专业数据治理案例集,汇集了100个一线政企数据治理实践案例,覆盖13大行业和500业务场景,通过深入剖析数据治理难题,提供了新思路和实战经验&#xff0c…...

【51单片机】LED点阵屏 原理 + 使用

学习使用的开发板:STC89C52RC/LE52RC 编程软件:Keil5 烧录软件:stc-isp 开发板实图: 文章目录 LED点阵屏显示原理74HC595 编码LED点阵屏显示笑脸LED点阵屏显示动画 LED点阵屏 点阵屏在开发板的右上角,注意使用前需要…...

Java基于SpringBoot+Vue的宠物共享平台的设计与实现(附源码,文档)

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…...

【案例】Excel使用宏来批量插入图片

一、场景介绍 我有一个excel文件,需要通过一列的文件名称,按照规则给批量上传图片附件。 原始文件: 成功后文件: 二、实现方法 1. 使用【wps】工具打开Excel文件,将其保存为启用宏的文件。 2.找到编辑宏的【VB编辑器…...

报名开启|开放原子大赛“Rust数据结构与算法学习赛”

开放原子大赛“Rust数据结构与算法学习赛”报名进行中,报名截止时间为11月17日。 为了进一步促进开源技术的发展,提升国内开源社区的创新能力和国际影响力,开放原子开源基金会与清华大学开源操作系统训练营等单位,共同举办本次Rus…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求&#xff…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...