Cómo escribir una sala de chat en Python
1. Introducción al curso
1. Introducción
Esta clase de proyecto es para implementar el servidor y el cliente de un programa de sala de chat simple.
2. Puntos de conocimiento
El lado del servidor involucra los módulos de asyncore, asynchat y socket, y el cliente usa los módulos de telnetlib, wx, time y thread.
3. Entorno requerido
Se requiere WxPython para escribir el cliente en esta lección. Es un kit de herramientas GUI para instalarlo primero:
<. p>$ sudo apt-get install python-wxtoolsLa contraseña es shiyanlou
4. Captura de pantalla del efecto del proyecto
Ventana de inicio de sesión
Ventana de chat
2. Proyecto de combate real (lado del servidor)
1. Clase de servidor
Primero necesitas un servidor de chat, que se implementa aquí por heredando la clase de despachador de asyncore. El código es el siguiente
clase ChatServer(dispatcher):
"""
Servidor de chat
def __init__(self, puerto):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM )
self.set_reuse_addr()
self.bind(('', puerto))
self.listen(5)
self.users = {}
self.main_room = ChatRoom(self)
def handle_accept(self):
conn, addr = self.accept( )
ChatSession( self, conn)
2. Clase de sesión
Con la clase de servidor, también es necesario mantener la sesión de conexión de cada usuario. Esto se implementa heredando la clase async_chat de asynchat. El código es el siguiente:
clase ChatSession(async_chat):
"""
Responsable de la comunicación. con usuarios únicos
"""
def __init__(self, server, sock):
async_chat.__init__(self, sock)
self.server = servidor
self.set_terminator(' \n')
self.data = []
self.name = Ninguno p>
self.enter(LoginRoom(server))
def enter(self, room):
'Eliminar self de la sala actual y luego agregarlo a la habitación especificada. room'
prueba:
cur = self .room
excepto AttributeError:
pass
otro:
cur.remove(self)
self .room = room
room.add(self)
def recolectar_incoming_data(self, data):
'Aceptar datos del cliente'
self.data.append(data)
def found_terminator(self):
'Procesamiento cuando finaliza un dato del cliente'
line = ''.join(self.data)
self.data = []
prueba:
self.room.handle(self, line) p>
e
xcept EndSession:
self.handle_close()
def handle_close(self):
async_chat.handle_close(self)
self. enter(LogoutRoom(self.server))
3. Intérprete de comandos
Ahora necesita un intérprete de comandos que pueda interpretar comandos de usuario, como iniciar sesión, consultar usuarios en línea y enviar. mensajes Espera, el código es el siguiente:
clase CommandHandler:
"""
Clase de procesamiento de comandos
"""
def desconocido(self, sesión, cmd):
'Respuesta a comando desconocido'
session.push('Comando desconocido: %s\n' % cmd)
def handle(self, session, line):
'Procesamiento de comandos'
si no line.strip():
regresar p>
partes = line.split(' ', 1)
cmd = partes[0]
prueba:
línea = partes[1 ].strip()
IndexError:
línea = ''
meth = getattr(self, 'do_' + cmd, Ninguno )
intenta:
meth(sesión, línea)
excepto TypeError:
self.unknown(sesión, cmd) p>
4. Sala
A continuación, necesitamos implementar la sala de chat. Aquí definimos tres tipos de salas, a saber, la sala cuando el usuario inicia sesión por primera vez, la sala de chat y la sala cuando. el usuario cierra sesión en estas tres salas. Cada sala tiene una clase principal pública, el código es el siguiente:
class Room(CommandHandler):
"""
<. p>Contiene un entorno de múltiples usuarios, responsable del procesamiento y transmisión de comandos básicos"""
def __init__(self, server):
self.server = server
self.sessions = []
def add(self, session):
'Un usuario entra a la sala'
self.sessions.append (sesión)
def remove(self, sesión):
'Un usuario sale de la sala'
self.sessions.remove( session)
def broadcast(self, line):
'Enviar mensaje especificado a todos los usuarios'
para la sesión en self.sessions:
session. push(line)
def do_logout(self, session, line):
'Salir de la sala'
raise EndSession
clase LoginRoom (Sala):
"""
La sala del usuario que acaba de iniciar sesión
"""
def add(self, session ):
'Respuesta para conexión de usuario exitosa'
Room.a
dd(self, session)
session.push('Connect Success')
def do_login(self, session, line):
'Procesamiento del comando de inicio de sesión '
nombre = line.strip()
si no nombre:
session.push('Nombre de usuario vacío')
elif nombre en self.server.users:
session.push('UserName Exist')
otro:
session.name = nombre
session.enter(self.server.main_room)
clase ChatRoom(Sala):
"""
Sala de chat
"""
def add(self, session):
'Transmitir entrada de nuevo usuario'
session.push('Inicio de sesión exitoso') p>
self.broadcast(session.name + 'ha entrado a la sala.\n')
self.server.users[session.name] = sesión
Sala .add(self, session)
def remove(self, session):
'Transmitir al usuario para que abandone'
Room.remove(self, session)
self.broadcast(session.name + ' ha abandonado la sala.\n')
def do_say(self, session, line):
' El cliente envía mensaje'
self.broadcast(session.name + ': ' + línea + '\n')
def do_look(self, session, line):
'Ver usuarios en línea'
session.push('Usuarios en línea:\n')
para otros en self.sessions:
sesión .push(other.name + '\n')
clase LogoutRoom(Room):
"""
La sala cuando el usuario sale
p>"""
def add(self, session):
'Eliminar del servidor'
intenta:
del self.server.users[session.name]
excepto KeyError:
pass
5. Código completo del lado del servidor
#!/usr/bin/python
# codificación: utf-8
desde asyncore import despachador
desde asynchat import async_chat
importar socket, asyncore
PORT = 6666 #Port
clase EndSession(Exception):
"""
Sesión autodefinida
Excepción al final
"""
pasar
clase CommandHandler:
"""
Comando Clase de procesamiento
"""
def desconocido(self, sesión, cmd):
'Respuesta a comando desconocido'
sesión push('Comando desconocido: %s\n' % cmd)
def handle(self, session, line):
'Procesamiento de comandos'
si no, line.strip():
retorno
partes = line.split(' ', 1)
cmd = partes[0]
pruebe:
línea = partes[1].strip()
excepto IndexError:
línea = ''
meth = getattr(self, 'do_' + cmd, Ninguno)
prueba:
meth(sesión, línea)
excepto TypeError:
self.unknown(session, cmd)
class Room(CommandHandler):
"""
Un entorno que contiene múltiples usuarios, responsable de Procesamiento y transmisión de comandos básicos
"""
def __init__(self, server):
self.server = server
self .sessions = []
def add(self, session):
'Un usuario entra a la sala'
self.sessions.append(session)< / p>
def remove(self, session):
'Un usuario abandona la sala'
self.sessions.remove(sesión)
def broadcast (self, line):
'Enviar mensaje especificado a todos los usuarios'
para la sesión en self.sessions:
session.push(line)
def do_logout(self, session, line):
'Salir de la sala'
levantar EndSession
clase LoginRoom(Sala) :
"""
La sala del usuario que acaba de iniciar sesión
"""
def add(self, session ):
'Respuesta a la conexión exitosa del usuario'
Room.add(self, session)
session.push('Connect Success')
def do_login(self, session, line):
'Procesamiento del comando de inicio de sesión'
nombre = line.strip()
si no es nombre :
session.push('Nombre de usuario vacío')
nombre elif en self.server.users:
session.push('Nombre de usuario existe')
más:
session.name = nombre
session.enter(self.server.main_room)
clase ChatRoom(Sala):
""" p>
Sala de chat
"""
def add(self, session):
'Transmitir nuevos usuarios para ingresar'
session.push('Inicio de sesión exitoso')
self.broadcast(session.name + ' ha ingresado a la sala.\n')
self.server.users [ session.name] = session
Room.add(self, session)
def remove(self, session):
'Transmitir usuario para que se vaya'
Room.remove(self, session)
self.broadcast(session.name + ' ha abandonado la habitación.\n')
def do_say(self , sesión, línea):
'Cliente envía mensaje'
self.broadcast(session.name + ':' + línea + '\n')
def do_look(self, session, line):
'Ver usuarios en línea'
session.push('Usuarios en línea:\n')
para otro en self.sessions:
session.push(other.name + '\n')
clase LogoutRoom(Room):
"""
La sala cuando el usuario sale
"""
def add(self, session):
'Eliminar del servidor '
intenta:
del self.server.users[session.name]
excepto KeyError:
pass
clase ChatSession(async_chat):
"""
Responsable de comunicarse con un solo usuario
"""
def __init__ (self, servidor, calcetín):
async_chat.__init__(self, calcetín)
self.server = servidor
self.set_terminator('\n ' )
self.data = []
self.name = Ninguno
self.enter(LoginRoom(servidor))
def enter(self, room):
'Eliminar self de la habitación actual y luego agregarlo a la habitación especificada'
try:
cur = self .room
excepto AttributeError:
pasar
otro:
cur.remove(self)
self .habitación = habitación
habitación.add(self)
def recopilar_datos_entrantes(sel
f, datos):
'Aceptar datos del cliente'
self.data.append(data)
def found_terminator(self):
'Procesamiento cuando finaliza un dato del cliente'
line = ''.join(self.data)
self.data = []
intenta:
self.room.handle(self, line)
excepto EndSession:
self.handle_close()
def handle_close(self):
async_chat.handle_close(self)
self.enter(LogoutRoom(self.server))
clase ChatServer(dispatcher):
"""
Servidor de chat
"""
def __init__(self, puerto):
dispatcher.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(( ( '', puerto))
self.listen(5)
self.users = {}
self.main_room = ChatRoom(self) p >
def handle_accept(self):
conn, addr = self.accept()
ChatSession(self, conn)
if __name__ = = '__main__':
s = ChatServer(PORT)
prueba:
asyncore.loop()
excepto KeyboardInterrupt:
p>imprimir
3. Proyecto de combate real (cliente)
Después de completar el lado del servidor, debe implementar el cliente. Aquí el cliente usa telnetlib. Módulo para conectarse al servidor.
1. Ventana de inicio de sesión
El paquete de interfaz gráfica aquí usa wxPython. Hay instrucciones de instalación al frente. La ventana de inicio de sesión se implementa heredando la clase wx.Frame. siguiente:
clase LoginFrame(wx.Frame):
"""
Ventana de inicio de sesión