当前位置: 代码迷 >> 综合 >> study Python 30day (python项目 005 )
  详细解决方案

study Python 30day (python项目 005 )

热度:26   发布时间:2024-01-26 00:37:02.0

聊天室

client

import wx
import telnetlib
from time import sleep
import _thread as threadclass LoginFrame(wx.Frame):"""登录窗口"""def __init__(self, parent, id, title, size):# 初始化,添加控件并绑定事件wx.Frame.__init__(self, parent, id, title)self.SetSize(size)self.Center()self.serverAddressLabel = wx.StaticText(self, label="Server Address", pos=(10, 50), size=(120, 25))self.userNameLabel = wx.StaticText(self, label="UserName", pos=(40, 100), size=(120, 25))self.serverAddress = wx.TextCtrl(self, pos=(120, 47), size=(150, 25))self.userName = wx.TextCtrl(self, pos=(120, 97), size=(150, 25))self.loginButton = wx.Button(self, label='Login', pos=(80, 145), size=(130, 30))# 绑定登录方法self.loginButton.Bind(wx.EVT_BUTTON, self.login)self.Show()def login(self, event):# 登录处理try:serverAddress = self.serverAddress.GetLineText(0).split(':')con.open(serverAddress[0], port=int(serverAddress[1]), timeout=10)response = con.read_some()if response != b'Connect Success':self.showDialog('Error', 'Connect Fail!', (200, 100))returncon.write(('login ' + str(self.userName.GetLineText(0)) + '\n').encode("utf-8"))response = con.read_some()if response == b'UserName Empty':self.showDialog('Error', 'UserName Empty!', (200, 100))elif response == b'UserName Exist':self.showDialog('Error', 'UserName Exist!', (200, 100))else:self.Close()ChatFrame(None, 2, title='ShiYanLou Chat Client', size=(500, 400))except Exception:self.showDialog('Error', 'Connect Fail!', (95, 20))def showDialog(self, title, content, size):# 显示错误信息对话框dialog = wx.Dialog(self, title=title, size=size)dialog.Center()wx.StaticText(dialog, label=content)dialog.ShowModal()class ChatFrame(wx.Frame):"""聊天窗口"""def __init__(self, parent, id, title, size):# 初始化,添加控件并绑定事件wx.Frame.__init__(self, parent, id, title)self.SetSize(size)self.Center()self.chatFrame = wx.TextCtrl(self, pos=(5, 5), size=(490, 310), style=wx.TE_MULTILINE | wx.TE_READONLY)self.message = wx.TextCtrl(self, pos=(5, 320), size=(300, 25))self.sendButton = wx.Button(self, label="Send", pos=(310, 320), size=(58, 25))self.usersButton = wx.Button(self, label="Users", pos=(373, 320), size=(58, 25))self.closeButton = wx.Button(self, label="Close", pos=(436, 320), size=(58, 25))# 发送按钮绑定发送消息方法self.sendButton.Bind(wx.EVT_BUTTON, self.send)# Users按钮绑定获取在线用户数量方法self.usersButton.Bind(wx.EVT_BUTTON, self.lookUsers)# 关闭按钮绑定关闭方法self.closeButton.Bind(wx.EVT_BUTTON, self.close)thread.start_new_thread(self.receive, ())self.Show()def send(self, event):# 发送消息message = str(self.message.GetLineText(0)).strip()if message != '':con.write(('say ' + message + '\n').encode("utf-8"))self.message.Clear()def lookUsers(self, event):# 查看当前在线用户con.write(b'look\n')def close(self, event):# 关闭窗口con.write(b'logout\n')con.close()self.Close()def receive(self):# 接受服务器的消息while True:sleep(0.6)result = con.read_very_eager()if result != '':self.chatFrame.AppendText(result)if __name__ == '__main__':app = wx.App()con = telnetlib.Telnet()LoginFrame(None, -1, title="Login", size=(320, 250))app.MainLoop()

server

import asynchat
import asyncore# 定义端口
PORT = 6666# 定义结束异常类
class EndSession(Exception):passclass ChatServer(asyncore.dispatcher):"""聊天服务器"""def __init__(self, port):asyncore.dispatcher.__init__(self)# 创建socketself.create_socket()# 设置 socket 为可重用self.set_reuse_addr()# 监听端口self.bind(('', port))self.listen(5)self.users = {}self.main_room = ChatRoom(self)def handle_accept(self):conn, addr = self.accept()ChatSession(self, conn)class ChatSession(asynchat.async_chat):"""负责和客户端通信"""def __init__(self, server, sock):asynchat.async_chat.__init__(self, sock)self.server = serverself.set_terminator(b'\n')self.data = []self.name = Noneself.enter(LoginRoom(server))def enter(self, room):# 从当前房间移除自身,然后添加到指定房间try:cur = self.roomexcept AttributeError:passelse:cur.remove(self)self.room = roomroom.add(self)def collect_incoming_data(self, data):# 接收客户端的数据self.data.append(data.decode("utf-8"))def found_terminator(self):# 当客户端的一条数据结束时的处理line = ''.join(self.data)self.data = []try:self.room.handle(self, line.encode("utf-8"))# 退出聊天室的处理except EndSession:self.handle_close()def handle_close(self):# 当 session 关闭时,将进入 LogoutRoomasynchat.async_chat.handle_close(self)self.enter(LogoutRoom(self.server))class CommandHandler:"""命令处理类"""def unknown(self, session, cmd):# 响应未知命令# 通过 aynchat.async_chat.push 方法发送消息session.push(('Unknown command {} \n'.format(cmd)).encode("utf-8"))def handle(self, session, line):line = line.decode()# 命令处理if not line.strip():returnparts = line.split(' ', 1)cmd = parts[0]try:line = parts[1].strip()except IndexError:line = ''# 通过协议代码执行相应的方法method = getattr(self, 'do_' + cmd, None)try:method(session, line)except TypeError:self.unknown(session, cmd)class Room(CommandHandler):"""包含多个用户的环境,负责基本的命令处理和广播"""def __init__(self, server):self.server = serverself.sessions = []def add(self, session):# 一个用户进入房间self.sessions.append(session)def remove(self, session):# 一个用户离开房间self.sessions.remove(session)def broadcast(self, line):# 向所有的用户发送指定消息# 使用 asynchat.asyn_chat.push 方法发送数据for session in self.sessions:session.push(line)def do_logout(self, session, line):# 退出房间raise EndSessionclass LoginRoom(Room):"""处理登录用户"""def add(self, session):# 用户连接成功的回应Room.add(self, session)# 使用 asynchat.asyn_chat.push 方法发送数据session.push(b'Connect Success')def do_login(self, session, line):# 用户登录逻辑name = line.strip()# 获取用户名称if not name:session.push(b'UserName Empty')# 检查是否有同名用户elif name in self.server.users:session.push(b'UserName Exist')# 用户名检查成功后,进入主聊天室else:session.name = namesession.enter(self.server.main_room)class LogoutRoom(Room):"""处理退出用户"""def add(self, session):# 从服务器中移除try:del self.server.users[session.name]except KeyError:passclass ChatRoom(Room):"""聊天用的房间"""def add(self, session):# 广播新用户进入session.push(b'Login Success')self.broadcast((session.name + ' has entered the room.\n').encode("utf-8"))self.server.users[session.name] = sessionRoom.add(self, session)def remove(self, session):# 广播用户离开Room.remove(self, session)self.broadcast((session.name + ' has left the room.\n').encode("utf-8"))def do_say(self, session, line):# 客户端发送消息self.broadcast((session.name + ': ' + line + '\n').encode("utf-8"))def do_look(self, session, line):# 查看在线用户session.push(b'Online Users:\n')for other in self.sessions:session.push((other.name + '\n').encode("utf-8"))if __name__ == '__main__':s = ChatServer(PORT)try:print("chat serve run at '0.0.0.0:{0}'".format(PORT))asyncore.loop()except KeyboardInterrupt:print("chat server exit")

 

  相关解决方案