使用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.rhkb.cn/news/466439.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ENSP作业——园区网

题目 根据上图,可得需求为: 1.配置交换机上的VLAN及IP地址。 2.设置SW1为VLAN 2/3的主根桥,设置SW2为VLAN 20/30的主根桥,且两台交换机互为主备。 3.可以使用super vlan。 4.上层通过静态路由协议完成数据通信过程。 5.AR1作为企…

【1个月速成Java】基于Android平台开发个人记账app学习日记——第7天,申请阿里云SMS短信服务SDK

系列专栏链接如下,方便跟进: https://blog.csdn.net/weixin_62588253/category_12821860.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12821860&sharereferPC&sharesourceweixin_62588253&sharefromfrom_link 同时篇幅…

让Apache正确处理不同编码的文件避免中文乱码

安装了apache2.4.39以后&#xff0c;默认编码是UTF-8&#xff0c;不管你文件是什么编码&#xff0c;统统按这个来解析&#xff0c;因此 GB2312编码文件内的中文将显示为乱码。 <!doctype html> <html> <head><meta http-equiv"Content-Type" c…

『Django』初识前后端分离

点赞 + 关注 + 收藏 = 学会了 本文简介 在前面的「Django」系列的文章 中使用的是“前后端不分离”的方式去学习 Django,但现在企业比较流行的开发方式是前后端分离。 简单来说,前后端分离就是把前端和后端的工作分配给2个人做,前端主要负责用户界面的开发,后端主要负责…

探索开放资源上指令微调语言模型的现状

人工智能咨询培训老师叶梓 转载标明出处 开放模型在经过适当的指令调整后&#xff0c;性能可以与最先进的专有模型相媲美。但目前缺乏全面的评估&#xff0c;使得跨模型比较变得困难。来自Allen Institute for AI和华盛顿大学的研究人员们进行了一项全面的研究&#xff0c;探索…

搜维尔科技:【应用】Xsens在荷兰车辆管理局人体工程学评估中的应用

荷兰车辆管理局&#xff08;RDW&#xff09;通过数据驱动的人体工程学评估&#xff0c;将职业健康和安全放在首位。 关键信息 01 改进人体工程学评估&#xff1a;RDW使用Xsens动作捕捉和Scalefit Industrial Athlete进行精确、实时的人体工程学评估&#xff0c;识别并降低与…

文件系统和日志管理 附实验:远程访问第一台虚拟机日志

文件系统和日志管理 文件系统&#xff1a;文件系统提供了一个接口&#xff0c;用户用来访问硬件设备&#xff08;硬盘&#xff09;。 硬件设备上对文件的管理 文件存储在硬盘上&#xff0c;硬盘最小的存储单位是512字节&#xff0c;扇区。 文件在硬盘上的最小存储单位&…

大众汽车合肥社招入职笔试测评SHL题库:综合能力、性格问卷、英语口语真题考什么?

大众汽车合肥社招入职笔试测评包括综合能力测试、性格问卷和英语口语测试。以下是各部分的具体内容&#xff1a; 1. **综合能力测试**&#xff1a; - 这部分测试需要46分钟完成&#xff0c;建议准备计算器和纸笔。 - 测试内容涉及问题解决能力、数值计算能力和逻辑推理能力。 -…

Python进阶之IO操作

文章目录 一、文件的读取二、文件内容的写入三、之操作文件夹四、StringIO与BytesIO 一、文件的读取 在python里面&#xff0c;可以使用open函数来打开文件&#xff0c;具体语法如下&#xff1a; open(filename, mode)filename&#xff1a;文件名&#xff0c;一般包括该文件所…

UE5.4 PCG 自定义PCG蓝图节点

ExecuteWithContext&#xff1a; PointLoopBody&#xff1a; 效果&#xff1a;点密度值与缩放成正比

Transformer和BERT的区别

Transformer和BERT的区别比较表&#xff1a; 两者的位置编码&#xff1a; 为什么要对位置进行编码&#xff1f; Attention提取特征的时候&#xff0c;可以获取全局每个词对之间的关系&#xff0c;但是并没有显式保留时序信息&#xff0c;或者说位置信息。就算打乱序列中token…

Apache Commons Collections 反序列化漏洞

文章目录 前言一、漏洞爆出二、复现环境java集合框架问题JVM反射 三、Apache Commons Collections漏洞原理≤3.2.1CC关键类调用链路POC构造思路POC 前言 Apache Commons Collections是一个扩展了Java标准库里的Collection结构的第三方基础库&#xff0c;它提供了很多强大的数据…

正则表达式1 re.match惰性匹配详解案例

点个关注 re.match() re.match() 函数尝试从字符串的开头开始匹配一个模式&#xff0c;如果匹配成功&#xff0c;返回一个匹配成功的对象&#xff0c;否则返回None。大小写区分&#xff0c;内容匹配不到后面的,只能匹配一个&#xff0c;不能有空格&#xff08;开头匹配&#…

gov企业征信系统瑞数6vmp算法还原

URL aHR0cHM6Ly9zZC5nc3h0Lmdvdi5jbi8今天再来逆向下国家企业征信系统&#xff0c;这个站很卡&#xff0c;兄弟们你们轻点爬&#xff0c;我刷以下页面就转好久的圈圈&#xff0c;这个站两层防护&#xff0c;一层加速乐&#xff0c;一层瑞数&#xff0c;貌似还有极验验证码防护…

代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础

目录 图论理论基础 深度优先搜索理论基础 卡玛网 98.所有可达路径 广度优先搜索理论基础 图论理论基础 图论理论基础 | 代码随想录 图的基本概念 图的种类 大体分为有向图和无向图。 图中的边有方向的是有向图&#xff1a; 图中的边没有方向的是无向图&#xff1a; 图…

【自学笔记】神经网络(1)

文章目录 介绍模型结构层&#xff08;Layer&#xff09;神经元 前向传播反向传播Q1: 为什么要用向量Q2: 不用激活函数会发生什么 介绍 我们已经学习了简单的分类任务和回归任务&#xff0c;也认识了逻辑回归和正则化等技巧&#xff0c;已经可以搭建一个简单的神经网络模型了。 …

详解Python面向对象程序设计

Python面向对象程序设计 1&#xff0c;初识类和对象2&#xff0c;类的定义和使用3&#xff0c;构造方法4&#xff0c;常用的类内置方法4.1&#xff0c;字符串方法&#xff1a;__str__ 4.2&#xff0c;是否小于&#xff1a;__lt__4.3&#xff0c;是否小于等于&#xff1a;__le__…

超级大项目招标:1000台AGV,12月13日截至

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 近期&#xff0c;一个重磅招标项目引发业界广泛关注&#xff1a;焦作机器人应用产业研究院发布总额高达11380万元的机器人采购项目&#xff0c;其中包括1000台AGV&#xff08;无人叉车…

内部知识库:优化企业培训流程的关键驱动力

在当今快速变化的商业环境中&#xff0c;企业培训的重要性日益凸显。内部知识库作为整合、管理和分享企业内部学习资源的关键工具&#xff0c;正逐步成为优化企业培训流程的核心。以下将探讨内部知识库如何通过多种功能&#xff0c;助力企业提升培训效率、质量和员工满意度。 …

宏集Cogent DataHub: 高效实现风电场数据集中管理与自动化

01 案例概况 一家跨国电力公司使用宏集Cogent DataHub软件&#xff0c;在美国西南地区建立起风电场的集中控制和数据采集系统。该系统整合来自不同风力涡轮机的 OPC 服务器数据&#xff0c;并确保数据安全、实时的上传至中心 SCADA 系统和 Pi 数据库。这一解决方案实现了与现有…