欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > Python学习总结

Python学习总结

2025/2/24 7:18:04 来源:https://blog.csdn.net/2301_81186499/article/details/145815443  浏览:    关键词:Python学习总结

客户端与服务端聊天窗口

服务端
导入
wxPython 用于创建图形界面。
socket 用于网络通信,AF_INET 是 IPv4 地址族,SOCK_STREAM 表示流式套接字(TCP)。

利用wxPython 创建图形界面,并通过 socket 与服务器通信。

主要功能:

  • 连接服务器。
  • 发送和接收消息。
  • 断开连接。
  • 界面上有文本框和按钮来操作。
  • wxPython 处理 UI 部分,socket 处理网络通信。
import threading
from threading import main_thread, Thread
#coding UTF-8
import self
import wx
import time
from socket import socket,AF_INET,SOCK_STREAMclass YsjServer(wx.Frame):
//通过继承 wx.Frame,我们可以创建一个带有窗口的应用程序。def __init__(self):wx.Frame.__init__(self,None,id=1002,title='某工作室界面')# 创建面板对象pl = wx.Panel(self)# 面板中放盒子box = wx.BoxSizer(wx.VERTICAL)# 可伸缩的网格布局fgz1 = wx.FlexGridSizer(wx.HSCROLL)start_server_btn = wx.Button(parent=pl, size=(133,40), label='启动')record_btn = wx.Button(parent=pl, size=(133, 40), label='保存聊天记录')stop_server_btn = wx.Button(parent=pl, size=(133, 40), label='离开')fgz1.Add(start_server_btn, 1, wx.TOP)fgz1.Add(record_btn, 1, wx.TOP )fgz1.Add(stop_server_btn, 1, wx.TOP)# (可伸缩的网络布局)添加到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=Falseself.host_port=('',8888)# 创建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=True#创建主线程对象main_thread=threading.Thread(target=self.do_work())#设置守护线程,父线程执行结束,子线程也自动关闭main_thread.demon=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_threadsession_thread.start()self.show_info_and_send_client('服务器通知', f'欢迎{user_name}进入聊天室!',time.strftime('%Y-%m-%d %H:%M:%S',time.localtime()))self.server_socket.close()def show_info_and_send_client(self, data_source, data, date_time):# 字符串操作send_data = f'{data_source}:{data}\n时间:{date_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对象时会话线程即启动def run(self) -> None:print(f'客户端:{self.user_name}已经和服务器连接成功,服务器启动一个会话线程')while self.isOn:# 从客户端接收数据 存储到data中data = self.client_socket.recv(1024).decode('utf-8')# 如果客户端点击断开按钮,先给服务器发送一句话, 消息自定义  Y-disconnect-SJ 自定义的结束词儿if data == 'Y-disconnect-SJ':self.isOn = Falseself.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=wx.App()server =YsjServer()server.Show()app.MainLoop()

客户端

import wx
#coding UTF-8
from socket import  socket,AF_INET,SOCK_STREAMclass YsJClient(wx.Frame):def __init__(self, client_name):#调用父类的初始化方法#None:表示没有父级窗口#id 表示窗口编号#pos  窗体打开的位置#size 窗体的大小,单位像素wx.Frame.__init__(self,None, id=1001, title=client_name + '的客户端界面',pos=wx.DefaultPosition, size=(400, 450))#创建面板对象pl = wx.Panel(self)#面板中放盒子box = wx.BoxSizer(wx.VERTICAL)# 可伸缩的网格布局fgz1 = wx.FlexGridSizer(wx.HSCROLL)# 水平方向布局# 创建两个按钮conn_btn = wx.Button(parent=pl, size=(200, 40), label='连接')dis_conn_btn = wx.Button(parent=pl, size=(200, 40), label='断开')# 把两个按钮放到可伸缩的网格布局fgz1.Add(conn_btn, 1, wx.TOP | wx.LEFT)fgz1.Add(dis_conn_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, 120), style=wx.TE_MULTILINE)box.Add(self.chat_text, 1, wx.ALIGN_CENTRE)#可绳索网格布局fgz1 = wx.FlexGridSizer(wx.HSCROLL)#两个按钮reset_btn = wx.Button(parent=pl, size=(200, 40), label='重置')send_btn = wx.Button(parent=pl, size=(200, 40), label='发送')fgz1.Add(reset_btn, 1, wx.TOP | wx.LEFT)fgz1.Add(send_btn, 1, wx.TOP | wx.RIGHT)# (可伸缩的网络布局)添加到box中box.Add(fgz1, 1, wx.ALIGN_CENTRE)pl.SetSizer(box)'--------客户端界面绘制--------'self.Bind(wx.EVT_BUTTON, self.connect_to_server, conn_btn)self.client_name=client_nameself.isConnected=Falseself.client_socket=None#发送绑定self.Bind(wx.EVT_BUTTON, self.send_to_server, send_btn)#断开绑定self.Bind(wx.EVT_BUTTON, self.dis_conn_to_server, dis_conn_btn)# 重置绑定self.Bind(wx.EVT_BUTTON, self.reset, reset_btn)def reset(self,event):self.chat_text.Clear()def dis_conn_to_server(self,event):self.client_socket.send('Y-disconnect-SJ'.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:server_host_port=('127.0.0.1',8888)#创建socket对象self.client_socket=socket(AF_INET,SOCK_STREAM)#发送请求self.client_socket.connect(server_host_port)import threading# 只要连接成功,发送一条数据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=wx.App()name=input('请输入客户端名称')client =YsJClient(name)client.Show()app.MainLoop()

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词