Una de las formas más comunes de implementar los sockets es a través del protocolo TCP, esto ayuda a que con el apoyo del sistema operativo la transmisión vía Internet se de manera normal y sin problemas.
Manipular el tiempo de espera del socket
Ya que conocemos un poco el concepto básico de lo que es sockets, vamos a empezar por manipular sus características, una de ellas es el tiempo de espera.
Para lograr esto podemos utilizar un par de métodos que existen con esa finalidad dentro de la librería estándar socket de Python.
Estableciendo el tiempo de espera
Vamos a crear ahora un pequeño programa que nos permita poner en acción lo que hemos aprendido, para ello vamos en primer lugar a crear un objeto del tipo socket que servirá como nuestro sujeto de pruebas, para ello le pasaremos la familia y el tipo de socket al constructor y con ello podremos aplicar los métodos.
Para poder ver los cambios una vez que hemos creado nuestro socket imprimiremos su tiempo de espera que debe ser nulo porque es un objeto nuevo, luego con el método settimeout() le estableceremos un nuevo tiempo de espera y finalmente vamos a imprimir la información, así confirmaremos que todo ha funcionado como debía.
Para lograr todo esto debemos asegurarnos de tener Python instalado en nuestro sistema, en su versión 2.7, y tener un editor de texto para poder crear los archivos con los programas, aunque también podemos hacer el ejercicio en la consola, sin embargo es un poco más incómodo y no es persistente, lo que quiere decir que perderíamos nuestro trabajo. Veamos el código fuente de este ejemplo:
#!/usr/bin/env python import socket def tiempo_espera_socket(): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "El tiempo de espera inicial es: %s" %s.gettimeout() s.settimeout(100) print "El nuevo tiempo de espera es: %s" %s.gettimeout() if __name__ == '__main__': tiempo_espera_socket()
Esto lo vamos a guardar en un nuevo archivo llamado socketTiempoEspera.py y lo ejecutaremos en consola, el resultado debe ser algo similar a lo siguiente:
Manipular el tamaño del buffer de un socket
El buffer es otra de las cosas que debemos tomar en cuenta cuando trabajamos con sockets, ya que este componente es el que nos va a indicar la cantidad de datos que podemos transmitir al momento, a mayor cantidad de buffer mayor es la cantidad de datos, sin embargo esto significa también más consumo de recursos y un mayor tiempo de espera en la transmisión de los mismos. En caso contrario un menor buffer representa más velocidad aunque limita la cantidad de datos a trasladar, es por ello que es una habilidad que debemos dominar.
Estableciendo el tamaño del buffer
Vamos a crear un pequeño programa para demostrar lo que hemos explicado anteriormente, en el código que veremos vamos en primer lugar a crear un par de constantes que utilizaremos en nuestro programa y serán definidas a 4096 lo que es un valor para el tamaño de los buffers que estableceremos.
Luego hacemos una instancia de la clase socket, para inmediatamente pedir los tamaños iniciales del buffer, luego los imprimimos por pantalla.
Finalmente utilizaremos el método setsockopt() para establecer el tamaño que deseamos del buffer utilizando las constantes definidas al inicio del programa, este método recibe tres parámetros, el nivel , el nombre y finalmente el valor para el buffer.
Veamos el código que nos ayuda a especificar lo que hemos explicado, vamos a guardarlo en un archivo llamado tamano_buffer.py:
#!/usr/bin/env python import socket TAM_BUFFER_ENVIO = 4096 TAM_BUFFER_RECEPCION = 4096 def manipular_buffer(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM ) # Get the size of the socket's send buffer tamanoBuffer = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) print "Tamano Buffer [Antes]:%d" %tamanoBuffer sock.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF,TAM_BUFFER_ENVIO) sock.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,TAM_BUFFER_RECEPCION) tamanoBuffer = sock.getsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF) print "Tamano Buffer [Despues]:%d" %tamanoBuffer if __name__ == '__main__': manipular_buffer()
Una vez que hemos escrito nuestro programa, vamos a proceder a ejecutarlo en consola y veremos que obtenemos los valores del buffer antes y después de modificar su tamaño.
El manejo de errores
Como con todo tipo de programas, al trabajar con sockets no estamos exentos de encontrarnos con algunos errores, el tema que debemos evitar es que estos errores nos tomen por sorpresa, ya que si lo hacen nuestra aplicación puede funcionar de forma impredecible.
Es por ello que debemos aprender a manejar los errores, de esta forma si ocurre una situación inesperada nuestro programa no muere si no que nos avisa que algo ha ocurrido, con ello evitaremos que haya corrupción de datos o situaciones similares que afectan la estabilidad de nuestra programa.
Haciendo un programa que maneje los errores
En el siguiente programa vamos a poner a prueba lo que hemos definido durante la explicación. En primer lugar vamos a crear un bloque que nos controle si la creación del socket ha tenido un error o no, con ello podremos asegurar un buen inicio de nuestro código.
Acto seguido vamos a evaluar la conexión de nuestra aplicación a un host remoto a través de un puerto en particular y con el manejo de errores podemos definir un mensaje personalizado. Finalmente hacemos el llamado a nuestra función y con ello ejecutaremos las acciones descritas.
Veamos el siguiente código que debemos almacenar en un archivo llamado errores_socket.py y luego lo ejecutaremos en consola:
#!/usr/bin/env python import sys import socket host = 'http://python.orgt' puerto = '06' def manejo_errores(): try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) except socket.error, e: print "Hubo un error al crear el socket: %s" % e sys.exit(1) try: s.connect((host, puerto)) except socket.gaierror, e: print "Error en la direccion de conexion: %s" % e sys.exit(1) except socket.error, e: print "Error de conexion: %s" % e sys.exit(1) if __name__ == '__main__': manejo_errores()
Aquí vemos que hemos utilizado la librería sys para poder utilizar el método exit() y cerrar el programa luego que ocurra un error. También notamos que el host está incorrecto esto es para que podamos forzar al error y así ver el mensaje en pantalla. Por último notamos que utilizamos la variable e para capturar el error del socket, con ello podremos obtener el detalle real de lo que ocurrió.
Es muy importante que leamos la documentación de la librería socket de Python para poder encontrar más y mejores formas de aprovechar sus recursos.
Con esto finalizamos este tutorial, nos hemos dado cuenta como Python tiene herramientas muy sencillas de entender que nos dan acceso al mundo de los sockets, con ello podremos empezar a programar aplicaciones que utilicen las redes para hacer procesamientos en tiempo real, como por ejemplo obtener información de otras máquinas de la red o incluso de Internet.