Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Proyecto 1 Sockets
Proyecto 1 Sockets
Proyecto 1.
Implementación Sockets.
Índice de Contenidos
1. Introducción 1
2. Marco Teórico 1
2.1. ¿Qué es un socket? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
2.2. ¿Cómo funciona un socket? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
5. Discusión 14
6. Conclusiones 14
Referencias 16
Índice de Figuras
1. Ilustración concepto de socket . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Índice de Códigos
1. Server inicialización . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2. Bucle que mantiene el Server activo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3. Función msg_to_all . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
4. Función que acepta a los clientes aceptarCon . . . . . . . . . . . . . . . . . . . . . . . 4
5. Función que procesa los mensajes de los clientes . . . . . . . . . . . . . . . . . . . . . . 4
6. Función procesarCon chequeo de nicknames. . . . . . . . . . . . . . . . . . . . . . . . . 5
7. procesarCon adición de oro. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
8. procesarCon salida de un cliente. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
9. procesarCon cantidad de oro y lista de usuarios conectados. . . . . . . . . . . . . . . . 6
10. procesarCon mensajes privados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
11. procesarCon cantidad de item asignado. . . . . . . . . . . . . . . . . . . . . . . . . . . 6
12. Bolsa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
13. Offer 1era parte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
14. Offer 2da parte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
15. Inicialización del cliente. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
16. Ingreso de nicknames. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
17. Ingreso de cantidad de oro inicial. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
18. Recepción de mensajes de otros clientes. . . . . . . . . . . . . . . . . . . . . . . . . . . 10
19. Bucle de input. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
20. Presentación de los comandos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
21. Emojis. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
22. Spawn. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
23. Offer. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
24. Accept y reject. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
25. Bolsa. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
26. Recepción de mensajes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
27. Envío de mensajes. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
1. Introducción
En el área de las telecomunicaciones, el término socket se refiere a un concepto abstracto a
partir del cual dos procesos pueden comunicarse e intercambiar información. Las propiedades de
un socket dependen de las características del protocolo en el que se implementan. Los protocolos
más comunes de implementación son TCP/IP y UDP.
Probablemente, la aplicación más conocida de los sockets TCP/IP es el chat. En esta tarea se
tiene por objetivo crear el chat de un juego del género MMORPG (Massively multiplayer online
role-playing game), en el cual los usuarios además de hablar, pueden intercambiar objetos entre
sí. El chat anteriormente mencionado, fue realizado en la plataforma Python, particularmente
utilizando Anaconda en la interfaz Spyder. En el presente informe se describe su implementación y
desarrollo.
2. Marco Teórico
2.1. ¿Qué es un socket?
Las computadoras actuales cuentan con componentes y sistemas complejos, por esta razón, están
equipadas con una capa de software llamada sistema operativo. El fin de este sistema es propor-
cionar a los usuarios un modelo de computador más sencillo, y encargarse de la administración de
todos los recursos que lo componen.
Los socket se pueden crear y distribuir en forma dinámica. Al crear un socket se devuelve un
descriptor de archivo, el cual se requiere para establecer una conexión, leer datos, escribir datos y
liberar la conexión.
Stream: los sockets de este tipo permiten comunicaciones fiables, estableciendo un circuito
virtual que une los dos puntos. Una vez establecida la conexión, se puede proceder al envío
secuencial de los datos. Este tipo de socket utiliza el protocolo TCP.
Raw: Permite el acceso a los protocolos de más bajo nivel (por ejemplo, el protocolo IP en el
dominio Internet).
Una vez que se crea un socket en los computadores de origen y de destino, se puede establecer
una conexión entre ellos. Una de las partes realiza una llamada al sistema listen en un socket local,
con lo cual se crea un buffer y se bloquea hasta que lleguen los datos. La otra parte realiza una
llamada al sistema connect y proporciona como parámetros el descriptor de archivo para un socket
local y la dirección de un socket remoto. Si la parte remota acepta la llamada, entonces el sistema
establece una conexión entre los sockets. Cuando el proceso ya no requiere la conexión, esta se
puede cerrar a través de la llamada al sistem close.
requerida de cada usuario y un listen que permite hasta 6 usuarios conectados. Se hace uso del
método sock.setblocking en la línea 13, ya que permite que el servidor no se quede anclado a un
solo cliente, dejando en espera a los demás.
Es importante destacar que se levantan dos hilos o threading, uno con el fin de aceptar y
mantener la conexión de los clientes, y otro con el objetivo de procesar los mensajes. Se observan
el las líneas 17 y 18 del Código 1.
4 self . clientes = []
5 self . nicks = [] # lista de nombres de de clientes
6 self .Nickname_Dic = {}
7 self .Oro_Dic = {}
8 self .items = {} # diccionario de items
9 self .sock = socket.socket(socket .AF_INET, socket.SOCK_STREAM)
10 #self.sock.bind((str (host) , int (port)))
11 self .sock.bind((host, port))
12 self .sock. listen (6)
13 self .sock.setblocking(False)
14
15 #Dos hilos, uno para aceptar y otro para procesar
16
17 aceptar= threading.Thread(target=self.aceptarCon)
18 procesar = threading.Thread(target=self.procesarCon)
19
20 aceptar.daemon = True
21 aceptar. start ()
22
23 procesar.daemon = True
24 procesar. start ()
El bucle que permite que el Server se mantenga activo constantemente se puede observar el
Código 2. Mientras no se le envíe un mensaje de salida (q) al servidor, la conexión se mantiene
constante. Este bucle también es parte de la primera función.
La segunda y tercera función están implementadas con el fin de enviar mensajes. La segunda
función, msg_to_all permite enviar mensajes a todos los clientes, removiendo clientes de la lista
self.clientes, en caso de que detecte que uno de ellos ya no está conectado. La tercera función
msg_to_one permite enviar mensajes a un cliente en particular.
Los mensajes se envían con el comando send y los clientes son removidos utilizando el comando
remove, como se puede observar en el Código 3.
La cuarta función, aceptarCon acepta a los clientes que se conectan al servidor y muestra un
aviso de conexión en la consola del servidor. También agrega el nuevo cliente a la lista self.clientes.
Consta de un bucle infinito que está permanentemente entregando una dirección y aceptando a los
nuevos usuarios que se conectan.
2 def aceptarCon(self) :
3 print("aceptarCon iniciado")
4 while True:
5 try :
6 conn, addre = self .sock.accept()
7 conn.setblocking(False)
8 aviso = ’[SERVER] Client: ’ + str(addre) + ’ connected!’
9 print(aviso)
10 self . clientes .append(conn)
11 except:
12 pass
Por último, se define la función para procesar las conexiones, esta contiene un while infinito que
recorre la lista de clientes para saber cuando se recibe un mensaje. Es la función dentro del código
que realiza la mayor cantidad de operaciones, puesto que interactúa directamente con los clientes.
Realiza las ofertas, el intercambio de items, la recepción de nicknames, etc.
9 if data:
Si existe mensaje enviado desde algún cliente, es decir, si se cumple que data existe, se realizan
los siguientes if.
Nickname: en la interfaz del cliente se pide insertar el nombre que el usuario desea tener
dentro del chat. Una vez ingresado, se envía al servidor para procesarlo. Si el nombre está en
uso se reenvía un mensaje al cliente para que ingrese un nombre distinto y si no, se guarda el
nombre en el diccionario de nicknames self.Nicknames_Dic.
Cantidad de oro: una vez que el cliente ingresa su cantidad de oro disponible en la interfaz
de cliente, esta se envía al servidor para ser almacenada en el diccionario correspondiente,
self.Oro_Dic y envíe un mensaje con la cantidad de oro asignado al cliente en particular.
Utiliza el marcador Initial_Gold_Assignator, como se puede observar en el Código 7.
Salida: si el mensaje del cliente es 0 q 0 , quiere decir que desea salir del chat y el servidor corta
la conexión removiendo su cantidad de oro, nickname y de la lista de clientes.
Consulta usuario: si el usuario desea saber la cantidad de oro que tiene disponible o los
usuarios conectados, puede enviar el mensaje gold o u al servidor respectivamente. En ese
caso el servidor le envía su cantidad de oro almacenada hasta el momento o la lista de
usuarios conectados.
Mensajes privados: si uno de los usuarios desea comunicarse de forma privada con otro, puede
enviar el mensaje p - <Usuario_Objetivo> - Mensaje, el cual es procesado por el servidor.
Utiliza el comando re.search el cual busca si existe un string dentro de otro string para enviar
el mensaje al usuario objetivo.
Spawn: genera la cantidad del objeto asignado por el cliente. Esto a partir del uso de un
diccionario, cuya llave es el objeto y la cantidad el valor. También utiliza marcadores para
verificar el mensaje del cliente.
Bolsa_Items: Este comando entrega la lista de items que posee el jugador que envía el co-
mando ’Bolsa’:
Offer: este comando consiste en 2 partes. Primero el cliente establece una oferta especificando
el item, cantidad y precio y la dirige a otro cliente, con previa revisión de los detalles de
la oferta (la conexión de la persona a quien ofrece en self.Nickname_Dic y la cantidad
suficiente de los items a intercambiar en self.items). Segundo al enviar la propuesta de
oferta existosamente al cliente correspondiente, este puede aceptar o rechazar la propuesta,
para el primer caso, se debe disponer de cantidad suficiente de oro para el intercambio de oro
e items en self.Oro_Dic y su luego entrega de items al comprador por parte del vendedor
a través de self.items, en el último caso, se envia un mensaje de oferta rechazada al cliente
que ofrece items por oro. Estos comandos también se realizan con la ayuda de marcadores.
Por último, si mensaje recibido al servidor no cumple ninguno de los requisitos para entrar
a alguno de los apartados anteriores, se interpreta como un mensaje que se le debe enviar al
resto de usuarios conectados:
1 else :
2 self .msg_to_all(bytes(’<’ + self .Nickname_Dic[c] + ’>’ + ’: ’ + pickle. loads(data), ’ utf-8
,→ ’ ) ,c)
Se verifica si el nickname ingresado por el cliente está en uso, se volverá a pedir hasta que
el cliente ingrese un nickname válido para luego enviarlo al servidor y ser guardado con la
información de su socket:
El cliente puede crear una cantidad de oro para iniciar el chat, se comprueba que éste sea un
número entero y positivo:
Se abre el proceso de recepción de mensajes de otros clientes y sin interferir con los mensajes
enviados.
Se abre un bucle para su constante envío de solicitud al servidor, con una secuencia de if,
excepto cuando el cliente ingresa ’q’, comando para salir del chat con self.sock.close():
El archivo cliente también dispone de un comando de ayuda, que al ingresar se presentan una
lista de comandos que puede utilizar el cliente aparte de chatear:
El comando emojis permite enviar caras digitales hacia otros clientes, gracias a la previa
definición de éstas en la inicialización del cliente:
Al ingresar "Spawn"se recolecta las informaciones del item y cantidad y se envían al servidor
para su luego adición al diccionario de items del cliente:
Con el comando offer, el cliente puede ingresar datos de la propuesta oferta que son recolec-
tados para luego enviarlos al sevidor y luego al cliente comprador:
Ingresando .accept.o reject"se cambian los marcadores predefinidos que permiten aceptar o no
la propuesta oferta llegada al cliente:
1 # Se acepta el intercambio
2 elif self .msg == ’accept’:
3 ACCEPT_FLAG = True
4 REJECT_FLAG = False
5
6 # Se rechaza el intercambio
7 elif self .msg == ’reject’:
8 ACCEPT_FLAG = False
9 REJECT_FLAG = True
En la recepción de mensajes se especifica el caso de cuando el cliente recibe una oferta, donde se ac-
tivan o desactivan los marcadores ACCEPT_FLAG, REJECT_FLAG y VERIFY_FLAG
según el caso de aceptar o rechazar una propuesta.
Se envían las solicitudes al servidor y los mensajes hacia otros clientes a través del uso del paquete
pickle:
5. Discusión
El desarrollo de la tarea se vio estancado por un largo período debido al poco manejo del formato
en el que se estaba trabajando. Si bien se conocía el concepto teórico de los sockets, se desconocía su
forma de implementación en el lenguaje utilizado, python. Una vez que se comprendió la forma de
envío y recepción de datos, además de como codificarlos/decodificarlos, fue posible realizar avances,
completando todos los requerimientos solicitados.
Otro aspecto a discutir, es que la implementación no funciona igual si se realiza en una interfaz
diferente a spyder. Al llevar a cabo la implementación en python propiamente tal, los mensajes
llegan de forma no fluida, quedando clientes en espera por un tiempo. Se cree que esto es posi-
blemente debido a que una interfaz cuenta con librerías que la otra no, ya que como se mencionó
anteriormente, el comando sock.setblocking debería evitar los tiempos de espera cliente-servidor.
6. Conclusiones
Se logró implementar tanto el servidor como cliente solicitados para esta actividad. La imple-
mentación de threads permitió tanto la conexión múltiple de un máximo de 6 usuarios distintos
por el lado del servidor, como el envío y recepción de mensajes entre clientes conectados al sevidor,
mostrándose estos mensajes en las consolas de cada usuario conectado. Estos usuarios fueron capa-
ces de designarse un identificador único por cada usuario, siendo notificados si el identificador ya
ha sido ocupado por otro usuario conectado. Por otra parte, una vez conectados al servidor, estos
usuarios son capaces de interactuar mediante una serie de comandos con otros usuarios conectados
al servidor, como crear e intercambiar objetos, enviar emojis, entre otros. Mediante diccionarios
se mantiene un registro por cada usuario de la moneda virtual ocupada dentro del chat, así como
también los items generados e intercambiados.Así, considerando lo anterior expuesto, se consideran
cumplidos exitósamente los objetivos propuestos para esta actividad.
Las dificultades presentes consistieron, en primer lugar, en el poco manejo previo del funcio-
namiento práctico de la implementación de sockets en Python, lo que retrasó considerablemente
los avances al elaborar el servidor y el cliente los primeros días. En segundo lugar, no se consideró
durante los primeros días el funcionamiento distinto de las interfaces de python al momento de
probar los códigos, lo que conllevó a que se retrasara el avance. Esto se solucionó una vez se utilizó
una interfaz común (Spyder).
Referencias
[1] Sockets con Python, [en línea].https://github.com/hcastillaq/Python-Sockets/blob/
master/Sockets_con_Python.pdf
[2] uma., El interfaz socket, [en línea] <http://www.lcc.uma.es/~eat/services/i_socket/i_
socket.html#link22>
[3] EcuRed., Socket, [en línea] <https://www.ecured.cu/Socket>
[4] Andrew S., Sistemas Operativos Modernos 3°edición., [en línea] <https://www.
lawebdelprogramador.com/pdf/14102-Sistemas-operativos-modernos.html>