Sala de chat simple usando Python

Este artículo demuestra: cómo configurar un servidor de sala de chat simple y permitir que varios clientes se conecten a él mediante un script del lado del cliente. El código utiliza el concepto de sockets y subprocesos. 
 

Programación de enchufes

Los sockets se pueden considerar como puntos finales en un canal de comunicación que es bidireccional y establece la comunicación entre un servidor y uno o más clientes. Aquí, configuramos un socket en cada extremo y permitimos que un cliente interactúe con otros clientes a través del servidor. El zócalo del lado del servidor se asocia con algún puerto de hardware del lado del servidor. Cualquier cliente que tenga un socket asociado con el mismo puerto puede comunicarse con el socket del servidor. 
 

subprocesos múltiples

Un subproceso es un subproceso que ejecuta un conjunto de comandos individualmente de cualquier otro subproceso. Por lo tanto, cada vez que un usuario se conecta al servidor, se crea un subproceso separado para ese usuario, y la comunicación del servidor al cliente se lleva a cabo a través de subprocesos individuales basados ​​en objetos de socket creados por el bien de la identidad de cada cliente. 
Necesitaremos dos scripts para establecer esta sala de chat. Uno para mantener el servicio en funcionamiento y otro que cada cliente debe ejecutar para conectarse al servidor. 
 

Script del lado del servidor

El script del lado del servidor intentará establecer un socket y vincularlo a una dirección IP y un puerto especificado por el usuario (es posible que los usuarios de Windows tengan que hacer una excepción para el número de puerto especificado en la configuración de su firewall, o pueden usar un puerto que ya está abierto). La secuencia de comandos permanecerá abierta y recibirá requests de conexión y agregará los objetos de socket respectivos a una lista para realizar un seguimiento de las conexiones activas. Cada vez que un usuario se conecte, 
se creará un hilo separado para ese usuario. En cada hilo, el servidor espera un mensaje y envía ese mensaje a otros usuarios que actualmente están en el chat. Si el servidor encuentra un error al intentar recibir un mensaje de un hilo en particular, saldrá de ese hilo. 
 

Uso

Este servidor se puede configurar en una red de área local eligiendo cualquiera en la computadora para que sea un Node de servidor y usando la dirección IP privada de esa computadora como la dirección IP del servidor. 
Por ejemplo, si una red de área local tiene un conjunto de direcciones IP privadas asignadas que van de 192.168.1.2 a 192.168.1.100, entonces cualquier computadora de estos 99 Nodes puede actuar como un servidor y los Nodes restantes pueden conectarse al Node del servidor mediante utilizando la dirección IP privada del servidor. Se debe tener cuidado al elegir un puerto que no esté actualmente en uso. Por ejemplo, el puerto 22 es el predeterminado para ssh y el puerto 80 es el predeterminado para los protocolos HTTP. Por lo tanto, estos dos puertos preferiblemente no deben usarse ni reconfigurarse para que estén libres para su uso. 
Sin embargo, si el servidor está destinado a ser accesible más allá de una red local, se requerirá la dirección IP pública para su uso. Esto requeriría el reenvío de puertos en los casos en que un Node de una red local (Node que no es el enrutador) desee alojar el servidor. En este caso, requeriríamos que cualquier solicitud que llegue a las direcciones IP públicas se redirija hacia nuestra dirección IP privada en nuestra red local y, por lo tanto, requeriríamos el reenvío de puertos. 
Para obtener más información sobre el reenvío de puertos: enlace
Para ejecutar el script, simplemente descárguelo del enlace de GitHub especificado en la parte inferior de la publicación y guárdelo en una ubicación conveniente en su computadora. 

/* Both the server and client script can then be run
   from the Command prompt (in Windows) or from bash 
   Terminal (Linux users) by simply typing 
   "python chat_server.py  " or "python client.py  ". 
   For example, */
python chat_server.py 192.168.55.13 8081
python client.py 192.168.55.13 8081

A continuación se muestra el script del lado del servidor que debe ejecutarse en todo momento para mantener la sala de chat en funcionamiento.

Python3

# Python program to implement server side of chat room.
import socket
import select
import sys
'''Replace "thread" with "_thread" for python 3'''
from thread import *
 
"""The first argument AF_INET is the address domain of the
socket. This is used when we have an Internet Domain with
any two hosts The second argument is the type of socket.
SOCK_STREAM means that data or characters are read in
a continuous flow."""
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
 
# checks whether sufficient arguments have been provided
if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()
 
# takes the first argument from command prompt as IP address
IP_address = str(sys.argv[1])
 
# takes second argument from command prompt as port number
Port = int(sys.argv[2])
 
"""
binds the server to an entered IP address and at the
specified port number.
The client must be aware of these parameters
"""
server.bind((IP_address, Port))
 
"""
listens for 100 active connections. This number can be
increased as per convenience.
"""
server.listen(100)
 
list_of_clients = []
 
def clientthread(conn, addr):
 
    # sends a message to the client whose user object is conn
    conn.send("Welcome to this chatroom!")
 
    while True:
            try:
                message = conn.recv(2048)
                if message:
 
                    """prints the message and address of the
                    user who just sent the message on the server
                    terminal"""
                    print ("<" + addr[0] + "> " + message)
 
                    # Calls broadcast function to send message to all
                    message_to_send = "<" + addr[0] + "> " + message
                    broadcast(message_to_send, conn)
 
                else:
                    """message may have no content if the connection
                    is broken, in this case we remove the connection"""
                    remove(conn)
 
            except:
                continue
 
"""Using the below function, we broadcast the message to all
clients who's object is not the same as the one sending
the message """
def broadcast(message, connection):
    for clients in list_of_clients:
        if clients!=connection:
            try:
                clients.send(message)
            except:
                clients.close()
 
                # if the link is broken, we remove the client
                remove(clients)
 
"""The following function simply removes the object
from the list that was created at the beginning of
the program"""
def remove(connection):
    if connection in list_of_clients:
        list_of_clients.remove(connection)
 
while True:
 
    """Accepts a connection request and stores two parameters,
    conn which is a socket object for that user, and addr
    which contains the IP address of the client that just
    connected"""
    conn, addr = server.accept()
 
    """Maintains a list of clients for ease of broadcasting
    a message to all available people in the chatroom"""
    list_of_clients.append(conn)
 
    # prints the address of the user that just connected
    print (addr[0] + " connected")
 
    # creates and individual thread for every user
    # that connects
    start_new_thread(clientthread,(conn,addr))    
 
conn.close()
server.close()

Script del lado del cliente

El script del lado del cliente simplemente intentará acceder al socket del servidor creado en la dirección IP y el puerto especificados. Una vez que se conecta, verificará continuamente si la entrada proviene del servidor o del cliente y, en consecuencia, redirige la salida. Si la entrada es del servidor, muestra el mensaje en la terminal. Si la entrada es del usuario, envía el mensaje que el usuario ingresa al servidor para que se transmita a otros usuarios.
Este es el script del lado del cliente, que cada usuario debe usar para conectarse al servidor.
 

Python3

# Python program to implement client side of chat room.
import socket
import select
import sys
 
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if len(sys.argv) != 3:
    print ("Correct usage: script, IP address, port number")
    exit()
IP_address = str(sys.argv[1])
Port = int(sys.argv[2])
server.connect((IP_address, Port))
 
while True:
 
    # maintains a list of possible input streams
    sockets_list = [sys.stdin, server]
 
    """ There are two possible input situations. Either the
    user wants to give manual input to send to other people,
    or the server is sending a message to be printed on the
    screen. Select returns from sockets_list, the stream that
    is reader for input. So for example, if the server wants
    to send a message, then the if condition will hold true
    below.If the user wants to send a message, the else
    condition will evaluate as true"""
    read_sockets,write_socket, error_socket = select.select(sockets_list,[],[])
 
    for socks in read_sockets:
        if socks == server:
            message = socks.recv(2048)
            print (message)
        else:
            message = sys.stdin.readline()
            server.send(message)
            sys.stdout.write("<You>")
            sys.stdout.write(message)
            sys.stdout.flush()
server.close()

Producción: 

En la imagen que se muestra a continuación, se ha inicializado un servidor en el lado izquierdo de la terminal y un script de cliente en el lado derecho de la terminal. (División de terminal hecha usando tmux, ‘sudo apt-get install tmux’). Para fines de inicialización, puede ver que cada vez que un usuario envía un mensaje, el mensaje junto con la dirección IP se muestra en el lado del servidor. 
 

Screenshot from 2017-04-18 18-31-03

La imagen de abajo tiene una conversación básica entre dos personas en el mismo servidor. ¡Múltiples clientes pueden conectarse al servidor de la misma manera! 
 

Screenshot from 2017-04-18 18-31-03

Enlace para descargar el script: enlace
Este artículo es una contribución de Deepak Srivatsav . Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo usando contribuya.geeksforgeeks.org o envíe su artículo por correo a contribuya@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.
Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente.
 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *