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

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

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

相关文章

基于STM32的温湿度监测器教学

引言 随着科技的发展,温湿度监测在农业、仓储、环境监测等领域的应用越来越广泛。本文将指导您如何基于STM32开发一个简单的温湿度监测器,使用常用的DHT11或DHT22传感器进行数据采集,并将监测结果显示在LCD或OLED屏幕上。 项目名称 STM32温湿…

科研绘图系列:R语言组合堆积图(stacked plot)

文章目录 介绍加载R包数据数据预处理画图1画图2组合图形系统信息介绍 堆积图(Stacked Chart),也称为堆叠图,是一种常用的数据可视化图表,主要用于展示不同类别的数据量在总体中的分布情况。堆积图可以是柱状图、条形图或面积图的形式,其中各个类别的数据量被叠加在一起,…

红黑树的平衡之舞:数据结构中的优雅艺术

文章目录 前言🚀一、红黑树的介绍1.1 红黑树的概念1.2 红黑树的特点1.3 红黑树的性质 🚀二、红黑树结点的定义🚀三、红黑树的框架🚀四、旋转操作🚀五、红黑树的插入操作5.1 uncle结点存在且为红5.2 uncle结点不存在或者…

ONLYOFFICE 8.2版本产品评测——遥遥领先,助力自动化办公

ONLYOFFICE 产品测试体验报告总结 知孤云出岫-CSDN博客 目录 产品介绍——篇【1】 一.关于 ONLYOFFICE 桌面编辑器 二.关于 ONLYOFFICE 协作空间 三.关于 ONLYOFFICE 文档 四.关于 ONLYOFFICE的版本介绍 产品新功能——篇【2】 一.关于 ONLYOFFICE的新增功能介绍 二.ONL…

【Linux驱动开发】通过设备树节点来配置和调用GPIO(pinctrl节点和gpio-controller)

【Linux驱动开发】通过设备树节点来配置和调用GPIO(pinctrl节点和gpio-controller) 文章目录 设备树下pinctrl节点GPIO控制节点调用方法GPIO输入附录:嵌入式Linux驱动开发基本步骤开发环境驱动文件编译驱动安装驱动自动创建设备节点文件 驱动…

【Linux】安装 SQL Server 命令行工具 mssql-tools18(Ubuntu 22.04)

引言 mssql-tools18 是一个包含 Microsoft SQL Server 命令行工具的软件包。这些工具包括 sqlcmd 和 bcp。 sqlcmd 是一个允许你用命令行与 SQL Server 进行交互的工具。你可以用它来运行 SQL 脚本,执行数据库维护任务,以及进行其他数据库管理操作。 b…

库存管理内训课件|39页PPT

文件是一份关于库存管理的内训课件,内容涵盖了库存管理的定义、分类、作用、存在的问题、管控目标以及具体管控措施。以下是对课件内容的总结: 1. 定义及分类 库存:为满足未来需求而暂时闲置的有价值的资源,与物品是否处于运动状…

大零售时代下融合发展的新路径:定制开发技术的应用与思考

摘要:本文探讨在大零售背景下,传统零售边界模糊,融合成为趋势。分析大零售包含的跨行业跨业态融合等三个层面,重点阐述定制开发技术中的 21 链动模式、AI 智能名片和 S2B2C 商城小程序在推动大零售发展中的作用和意义,…

OceanBase 安装使用详细说明

OceanBase 安装使用详细说明 一、系统环境要求二、安装OceanBase环境方案一:在线下载并安装all-in-one安装包方案二:离线安装all-in-one安装包安装前的准备工作三、配置OceanBase集群编辑配置文件部署和启动集群连接到集群集群状态和管理四、创建业务租户和数据库创建用户并赋…

基于LabVIEW应用ARINC 429板卡实现数据通讯——(下篇)

五、基于LabVIEW实现数据通讯 基于LabVIEW实现429板卡的数据通讯是调用API 动态链接库文件来实现的。该文件中有许多的板卡操作函数,在调用板卡中必须按照一定的函数调用流程来操作板卡,否则极易出现板卡操作错误。 1、API函数的调用步骤 API函数的调…

Android Studio打包时不显示“Generate Signed APK”提示信息

Android Studio打包时,默认显示“Generate Signed APK”提示信息,如下图所示: 如果在打包时不显示“Generate Signed APK”提示信息,解决办法是: Android Studio菜单栏,“File->Settings->Appearan…

典型的列转行(sparkSQL)

数据 id,username,math,computer,english 1,huangbo,34,58,58 2,xuzheng,45,87,45 3,wangbaoqiang,76,34,89 编写 SQL,将其转换为下面这张表 id,username,course,score 1,huangbo,math,34 1,huangbo,computer,58 1,huangbo,english,58 2,xuzheng,math,45 2,xuzheng,…

42python数据分析numpy基础之trace计算对角线元素的和

python的numpy库的trace()函数,计算对角线元素的和。 用法 numpy.trace(a, offset0, axis10, axis21, dtypeNone, outNone)描述 numpy.trace(a),返回数组a的对角线元素的和。 入参 a:必选,数组,列表,元…

信息安全工程师(68)可信计算技术与应用

前言 可信计算技术是一种计算机安全体系结构,旨在提高计算机系统在面临各种攻击和威胁时的安全性和保密性。 一、可信计算技术的定义与原理 可信计算技术通过包括硬件加密、受限访问以及计算机系统本身的完整性验证等技术手段,确保计算机系统在各种攻击和…

深度测评 ONLYOFFICE 文档 8.2 版本:革新与体验的双重提升

目录 深度测评 ONLYOFFICE 文档 8.2 版本:革新与体验的双重提升引言协作编辑功能的革新PDF 表单签名的创新界面设计的全面提升性能与稳定性的双重优化文档编辑器的新功能电子表格的强大新特性演示文稿的创意增强RTL 支持与本地化的关注更多实用改进用户体验的持续提…

CytoSPACE·单细胞与空间转录组的高精度对齐

CytoSPACE 是一种新型计算工具,用于将单细胞转录组分配到原位空间转录组学 (ST) 数据。该方法通过最短增强路径优化程序最小化基于相关性的成本函数来解决单细胞/点分配问题。 工作流程: 1. 应用现有的ST去卷积方法(如Spatial Seurat或RCTD&…

Matlab实现鲸鱼优化算法优化随机森林算法模型 (WOA-RF)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1内容介绍 鲸鱼优化算法(Whale Optimization Algorithm, WOA)是受座头鲸捕食行为启发而提出的一种新型元启发式优化算法。该算法通过模拟座头鲸围绕猎物的螺旋游动和缩小包围圈的方式,在…

Chrome 130 版本开发者工具(DevTools)更新内容

Chrome 130 版本开发者工具(DevTools)更新内容 一、网络(Network)面板更新 1. 重新定义网络过滤器 网络面板获新增了一些过滤条件,这些过滤条件是根据反馈重新设计的,特定于类型的过滤条件保持不变&…

扑克牌[CSP-J 2024]

题目传送 可以用map做成一个桶&#xff0c;它的size就是输入的种数&#xff0c;再用52-size就好了。 代码如下&#xff1a; #include<iostream> #include<map> using namespace std; typedef long long ll; int main() {map<string,int> b;int n;cin>&g…

【Spring IoC】容器和IoC介绍以及IoC程序开发的优势

文章目录 Spring 是什么什么是容器什么是 IoCIoC 介绍传统程序开发解决方法IoC 程序开发IoC 的优势 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 https://www.captainbed.cn/yechiel 在…