Categoria: Programacion Tema: Python Titulo: Sockets en python
Fecha del Tema: 2012-09-23 23:12:10 Sockets La comunicación entre distintas entidades en una red se basa en Python en el clásico concepto de sockets. Los sockets son un concepto abstracto con el que se designa al punto final de una conexión. Los programas utilizan sockets para comunicarse con otros programas, que pueden estar situados en computadoras distintas. Un socket queda definido por la dirección IP de la máquina, el puerto en el que escucha, y el protocolo que utiliza. Los tipos y funciones necesarios para trabajar con sockets se encuen- tran en Python en el módulo socket, como no podrÃa ser de otra forma. Los sockets se clasifican en sockets de flujo (socket.SOCK_STREAM) o sockets de datagramas (socket.SOCK_DGRAM) dependiendo de si el ser- vicio utiliza TCP, que es orientado a conexión y fiable, o UDP, respec- tivamente. En este capÃtulo sólo cubriremos los sockets de flujo, que cubren un 90% de las necesidades comunes. Los sockets también se pueden clasificar según la familia. Tenemos sockets UNIX (socket.AF_UNIX) que se crearon antes de la concepción de las redes y se basan en ficheros, sockets socket.AF_INET que son los que nos interesan, sockets socket.AF_INET6 para IPv6, etc. Para crear un socket se utiliza el constructor socket.socket() que pue- de tomar como parámetros opcionales la familia, el tipo y el protocolo. Por defecto se utiliza la familia AF_INET y el tipo SOCK_STREAM. Veremos durante el resto del capÃtulo cómo crear un par de programas cliente y servidor a modo de ejemplo. Lo primero que tenemos que hacer es crear un objeto socket para el servidor socket_s = socket.socket() Tenemos ahora que indicar en qué puerto se va a mantener a la escu- cha nuestro servidor utilizando el método bind. Para sockets IP, como es nuestro caso, el argumento de bind es una tupla que contiene el host y el puerto. El host se puede dejar vacÃo, indicando al método que puede utilizar cualquier nombre que esté disponible. socket_s.bind((â??localhost", 9999)) Por último utilizamos listen para hacer que el socket acepte conexio- nes entrantes y accept para comenzar a escuchar. El método listen requiere de un parámetro que indica el número de conexiones máximas que queremos aceptar; evidentemente, este valor debe ser al menos 1. El método accept se mantiene a la espera de conexiones entrantes, bloqueando la ejecución hasta que llega un mensaje. Cuando llega un mensaje, accept desbloquea la ejecución, devolviendo un objeto socket que representa la conexión del cliente y una tupla que contiene el host y puerto de dicha conexión. <? socket_s.listen(10) socket_c, (host_c, puerto_c) = socket_s.accept() ?> Una vez que tenemos este objeto socket podemos comunicarnos con el cliente a través suyo, mediante los métodos recv y send (o recvfrom y sendfrom en UDP) que permiten recibir o enviar mensajes respec- tivamente. El método send toma como parámetros los datos a enviar, mientras que el método recv toma como parámetro el número máxi- mo de bytes a aceptar. <? recibido = socket_c.recv(1024) print â??Recibido: â??, recibio socket_c.send(recibido) ?> Una vez que hemos terminado de trabajar con el socket, lo cerramos con el método close. Crear un cliente es aún más sencillo. Solo tenemos que crear el objeto socket, utilizar el método connect para conectarnos al servidor y uti- lizar los métodos send y recv que vimos anteriormente. El argumento de connect es una tupla con host y puerto, exactamente igual que bind. <? socket_c = socket.socket() socket_c.connect((â??localhost", 9999)) socket_c.send(â??hola") ?> Veamos por último un ejemplo completo. En este ejemplo el cliente manda al servidor cualquier mensaje que escriba el usuario y el servi- dor no hace más que repetir el mensaje recibido. La ejecución termina cuando el usuario escribe quit. Este serÃa el código del script servidor: <? import socket s = socket.socket() s.bind((â??localhost", 9999)) s.listen(1) sc, addr = s.accept() while True: recibido = sc.recv(1024) if recibido == â??quit": break print â??Recibido:", recibido sc.send(recibido) print â??adios" sc.close() s.close() ?> Y a continuación tenemos el del script cliente: <? view plaincopy to clipboardprint? import socket s = socket.socket() s.connect((â??localhost", 9999)) while True: mensaje = raw_input(â??> â??) s.send(mensaje) mensaje == â??quit": break print â??adios" s.close() ?>
Sockets La comunicación entre distintas entidades en una red se basa en Python en el clásico concepto de sockets. Los sockets son un concepto abstracto con el que se designa al punto final de una conexión. Los programas utilizan sockets para comunicarse con otros programas, que pueden estar situados en computadoras distintas. Un socket queda definido por la dirección IP de la máquina, el puerto en el que escucha, y el protocolo que utiliza. Los tipos y funciones necesarios para trabajar con sockets se encuen- tran en Python en el módulo socket, como no podrÃa ser de otra forma. Los sockets se clasifican en sockets de flujo (socket.SOCK_STREAM) o sockets de datagramas (socket.SOCK_DGRAM) dependiendo de si el ser- vicio utiliza TCP, que es orientado a conexión y fiable, o UDP, respec- tivamente. En este capÃtulo sólo cubriremos los sockets de flujo, que cubren un 90% de las necesidades comunes. Los sockets también se pueden clasificar según la familia. Tenemos sockets UNIX (socket.AF_UNIX) que se crearon antes de la concepción de las redes y se basan en ficheros, sockets socket.AF_INET que son los que nos interesan, sockets socket.AF_INET6 para IPv6, etc. Para crear un socket se utiliza el constructor socket.socket() que pue- de tomar como parámetros opcionales la familia, el tipo y el protocolo. Por defecto se utiliza la familia AF_INET y el tipo SOCK_STREAM. Veremos durante el resto del capÃtulo cómo crear un par de programas cliente y servidor a modo de ejemplo. Lo primero que tenemos que hacer es crear un objeto socket para el servidor socket_s = socket.socket() Tenemos ahora que indicar en qué puerto se va a mantener a la escu- cha nuestro servidor utilizando el método bind. Para sockets IP, como es nuestro caso, el argumento de bind es una tupla que contiene el host y el puerto. El host se puede dejar vacÃo, indicando al método que puede utilizar cualquier nombre que esté disponible. socket_s.bind((â??localhost", 9999)) Por último utilizamos listen para hacer que el socket acepte conexio- nes entrantes y accept para comenzar a escuchar. El método listen requiere de un parámetro que indica el número de conexiones máximas que queremos aceptar; evidentemente, este valor debe ser al menos 1. El método accept se mantiene a la espera de conexiones entrantes, bloqueando la ejecución hasta que llega un mensaje. Cuando llega un mensaje, accept desbloquea la ejecución, devolviendo un objeto socket que representa la conexión del cliente y una tupla que contiene el host y puerto de dicha conexión. <? socket_s.listen(10) socket_c, (host_c, puerto_c) = socket_s.accept() ?> Una vez que tenemos este objeto socket podemos comunicarnos con el cliente a través suyo, mediante los métodos recv y send (o recvfrom y sendfrom en UDP) que permiten recibir o enviar mensajes respec- tivamente. El método send toma como parámetros los datos a enviar, mientras que el método recv toma como parámetro el número máxi- mo de bytes a aceptar. <? recibido = socket_c.recv(1024) print â??Recibido: â??, recibio socket_c.send(recibido) ?> Una vez que hemos terminado de trabajar con el socket, lo cerramos con el método close. Crear un cliente es aún más sencillo. Solo tenemos que crear el objeto socket, utilizar el método connect para conectarnos al servidor y uti- lizar los métodos send y recv que vimos anteriormente. El argumento de connect es una tupla con host y puerto, exactamente igual que bind. <? socket_c = socket.socket() socket_c.connect((â??localhost", 9999)) socket_c.send(â??hola") ?> Veamos por último un ejemplo completo. En este ejemplo el cliente manda al servidor cualquier mensaje que escriba el usuario y el servi- dor no hace más que repetir el mensaje recibido. La ejecución termina cuando el usuario escribe quit. Este serÃa el código del script servidor: <? import socket s = socket.socket() s.bind((â??localhost", 9999)) s.listen(1) sc, addr = s.accept() while True: recibido = sc.recv(1024) if recibido == â??quit": break print â??Recibido:", recibido sc.send(recibido) print â??adios" sc.close() s.close() ?> Y a continuación tenemos el del script cliente: <? view plaincopy to clipboardprint? import socket s = socket.socket() s.connect((â??localhost", 9999)) while True: mensaje = raw_input(â??> â??) s.send(mensaje) mensaje == â??quit": break print â??adios" s.close() ?>