Blog
Creando conexión con Sockets en Python
- Publicado por: Rafael Fernandez
- Categoría: Blog
En ocasiones cuando programamos es necesario crear conexión entre dos programas o dispositivos. Afortunadamente, es posible lograrlo usando sockets.
En el presente tutorial aprenderemos de que se tratan los sockets y su utilidad para desarrollar una aplicación cliente/servidor, de modo que podamos intercambiar datos entre dos aplicaciones.
Definición de sockets
Cuando hablamos de sockets en programación, nos referimos al mecanismo que se encarga de intercambiar paquetes de datos entre dos programas que por lo general están situados en distintos ordenadores.
Los sockets son un concepto abstracto con el que se designa al punto final de una conexión.
Estos sockets pueden configurarse para trabajar como servidor o como cliente; para ello es necesario definir la dirección IP local y remota de ambos, al igual que el número de puerto y además contar con un protocolo de transporte.
De esta forma ambas partes se conectan y la comunicación se vuelve bidireccional.
Origen
Los sockets son una de las formas de IPC (Inter Process Comunication) más popular que existe. Fue inventado en Berkeley para ser usado en la variante BSD de Unix, pero más tarde se convirtió en la forma de comunicación más idónea en inter plataformas.
Tipos de sockets en Python
Existen diferentes tipos de sockets que se pueden crear con Python, y se encuentran en el módulo “socket”.
Estos sockets se clasifican básicamente:
- Sock_Stream o socket de flujo: Es un socket que utiliza TCP como protocolo de transmisión, con el cual hace posible que los mensajes enviados lleguen a su destino en el mismo orden en que se enviaron.
- Sock_Dgram o socket de datagrama: utiliza el protocolo UDP y en este caso los mensajes llegan en un orden diferente a como fue enviado originalmente.
Ahora bien, para crear un socket dentro del código, es preciso utilizar el constructor “socket.socket()” y entre los parámetros, indicar la familia de protocolos, el tipo de socket y el protocolo a utilizar. Veamos como ponerlo en práctica realizando una aplicación que funcione como cliente y otro como servidor.
Aplicación Cliente
El primer paso es importar los módulos necesarios para trabajar.
- Socket: manipula el socket que estamos creando.
- Sys: provee funcionalidades, directamente relacionadas con el intérprete. Lo usaremos con un subproceso que hace referencia a los errores que pueden producirse en la salida del programa.
import socket import sys
Luego utilizamos el constructor para crear un objeto socket TCP/IP.
objetoSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
El siguiente paso es conectar el socket al puerto en el momento que el servidor este escuchando. Esta expresión tiene dos parámetros: la IP del servidor y el puerto de conexión.
datos_servidor = ('localhost', 10000) print >>sys.stderr, 'conectando a %s puerto %s' % datos_servidor sock.connect(datos_servidor)
Teniendo lista la conexión podemos proceder a enviar la información que queramos a través del método sendall() y para recibirla usaremos el método recv().
Los parámetros del método sendall son los datos que se van a enviar, y el parámetro del recv es el número máximo de bytes a aceptar.
try: mensaje = 'Aquí va el mensaje' print >>sys.stderr, 'enviando "%s"' % mensaje objetoSocket.sendall(mensaje) # enviando el mensaje cantidad_recibida = 0 cantidad_esperada = len(mensaje) # recibiendo la respuesta while cantidad_recibida < cantidad_esperada: data = objetoSocket.recv(19) cantidad_recibida += len(data) print >>sys.stderr, 'recibiendo "%s"' % data
Por último, al terminar de trabajar con el socket sencillamente lo cerramos haciendo uso del método close().
finally: print >>sys.stderr, 'cerrando socket' objetoSocket.close()
Aplicación Servidor
Ahora crearemos el servidor. Para ello realizaremos algunos pasos similares a los que tomamos con el cliente; por ejemplo, la importación de módulos y creación del objeto socket TCP/IP.
import socket import sys objetoSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
Ahora bien, en este caso debemos asociar el socket con la dirección del servidor. Para ello empleamos el método bind() para así indicar que puerto debe escuchar y de que servidor debe esperar conexión.
datos_servidor = ('localhost', 10000) print >>sys.stderr, 'empezando a levantar %s puerto %s' % datos_servidor objetoSocket.bind(datos_servidor)
Por otra parte, para que nuestro socket sea capaz de aceptar la conexión que entra por parte del cliente y pueda escuchar el mensaje utilizaremos dos métodos: el método accept() y el método listen().
Con respecto al método listen, hemos de indicar en el parámetro, el número de conexiones entrantes que aceptaremos.
objetoSocket.listen(1) while True: print >>sys.stderr, 'Esperando para realizar conexión' connection, datos_cliente = objetoSocket.accept()
Y en relación al método accept(), este nos devuelve una conexión abierta entre el servidor y el cliente, además de la dirección ip del cliente. Como ya hemos visto anteriormente estos datos se leen y transmiten mediante recv() y sendall() respectivamente.
try: print >>sys.stderr, 'conexión desde', datos_cliente while True: data = connection.recv(19) print >>sys.stderr, 'recibido "%s"' % data if data: print >>sys.stderr, 'devolviendo mensaje al cliente' connection.sendall(data) else: print >>sys.stderr, 'no hay mas datos', datos_cliente break finally: connection.close()
Durante el proceso se reciben los datos en trozos y luego se retransmiten creando comunicación. Al terminar, la conexión se cierra usando el método close().