informatica:programacion:cursos:python_avanzado_proyectos_seguridad:introduccion_sockets
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| informatica:programacion:cursos:python_avanzado_proyectos_seguridad:introduccion_sockets [2024/11/11 15:53] – [Resumen] tempwin | informatica:programacion:cursos:python_avanzado_proyectos_seguridad:introduccion_sockets [2024/11/18 08:28] (actual) – [Módulo socket en Python] tempwin | ||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| ====== Introducción a los sockets ====== | ====== Introducción a los sockets ====== | ||
| + | <WRAP center round box 80%> | ||
| Módulo perteneciente al curso [[informatica: | Módulo perteneciente al curso [[informatica: | ||
| + | </ | ||
| Los sockets son el componente principal que nos permite aprovechar las capacidades del sistema operativo para interactuar con la red. Puede pensar en los sockets como un canal de comunicación punto a punto entre un cliente y un servidor. | Los sockets son el componente principal que nos permite aprovechar las capacidades del sistema operativo para interactuar con la red. Puede pensar en los sockets como un canal de comunicación punto a punto entre un cliente y un servidor. | ||
| - | Los sockets de red son una manera fácil de establecer una comunicación entre procesos que están en la misma máquina o en máquinas diferentes. El concepto de un socket es muy similar al de los descriptores de archivos UNIX. Los comandos como read() y write() que nos permiten trabajar con el sistema de archivos, funcionan de manera similar a los sockets. Una dirección de socket de red consta de una dirección IP y un número de puerto. El objetivo de un socket es comunicar procesos a través de la red. | + | Los sockets de red son una manera fácil de establecer una comunicación entre procesos que están en la misma máquina o en máquinas diferentes. El concepto de un socket es muy similar al de los descriptores de archivos UNIX. Los comandos como '' |
| <WRAP center round info 60%> | <WRAP center round info 60%> | ||
| Línea 25: | Línea 27: | ||
| Estos argumentos representan las familias de direcciones y el protocolo de la capa de transporte. Dependiendo del tipo de socket, los sockets se clasifican en sockets de flujo ('' | Estos argumentos representan las familias de direcciones y el protocolo de la capa de transporte. Dependiendo del tipo de socket, los sockets se clasifican en sockets de flujo ('' | ||
| - | 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. | + | Los sockets también se pueden clasificar según la familia. Tenemos sockets UNIX ('' |
| En la siguiente imagen vemos el constructor de la clase socket: | En la siguiente imagen vemos el constructor de la clase socket: | ||
| - | <WRAP center round important 60%> | + | {{ : |
| - | IMAAAAAAAAAAAAAAAAAAAAGEN | + | |
| - | </ | + | |
| ===== Módulo socket en Python ===== | ===== Módulo socket en Python ===== | ||
| Línea 47: | Línea 47: | ||
| </ | </ | ||
| - | <WRAP center round important 60%> | + | {{ : |
| - | IMAAAAAAAAAAAAAAAAAAAAAAAAAGEN | + | |
| - | </ | + | |
| En esta imagen vemos todas las constantes y métodos que tenemos disponibles en este módulo. Las constantes las vemos en primera instancia dentro de la estructura que ha devuelto el objeto. Entre las constantes más utilizadas podemos destacar: | En esta imagen vemos todas las constantes y métodos que tenemos disponibles en este módulo. Las constantes las vemos en primera instancia dentro de la estructura que ha devuelto el objeto. Entre las constantes más utilizadas podemos destacar: | ||
| Línea 58: | Línea 56: | ||
| Para abrir un socket en una determinada máquina utilizamos el constructor de la clase socket que acepta por parámetros la familia, el tipo de socket y el protocolo. Una llamada típica para construir un socket que funcione a nivel TCP& | Para abrir un socket en una determinada máquina utilizamos el constructor de la clase socket que acepta por parámetros la familia, el tipo de socket y el protocolo. Una llamada típica para construir un socket que funcione a nivel TCP& | ||
| - | <WRAP center round important 60%> | + | {{ : |
| - | IMAAAAAAAAAAAAAAAAAAAAAAAGEN | + | |
| - | </ | + | |
| <code python> | <code python> | ||
| Socket.socket(socket.AF_INET, | Socket.socket(socket.AF_INET, | ||
| </ | </ | ||
| - | |||
| - | ===== Recopilación de información con sockets ===== | ||
| - | |||
| - | Los métodos útiles para recopilar más información son: | ||
| - | |||
| - | * '' | ||
| - | * '' | ||
| - | |||
| - | Podemos obtener más información sobre estos métodos con el comando de '' | ||
| - | |||
| - | <WRAP center round todo 60%> | ||
| - | IMAAAAAAAAAAAAAAAAAAAAAAAAGEN | ||
| - | </ | ||
| - | |||
| - | Ahora vamos a detallar algunos métodos relacionados con el host, la dirección IP y la resolución del dominio. Para cada uno, mostraremos un ejemplo simple: | ||
| - | |||
| - | ==== socket.gethostbyname(hostname) ==== | ||
| - | |||
| - | Este método convierte un nombre de host al formato de dirección IPv4. La dirección IPv4 se devuelve en forma de cadena. Este método es equivalente al comando '' | ||
| - | |||
| - | <code python> | ||
| - | >>> | ||
| - | >>> | ||
| - | |||
| - | ' | ||
| - | |||
| - | >>> | ||
| - | |||
| - | ' | ||
| - | </ | ||
| - | |||
| - | ==== socket.gethostbyname_ex(nombre) ==== | ||
| - | |||
| - | Este método devuelve muchas direcciones IP para un solo nombre de dominio. Significa que un dominio se ejecuta en múltiples IP | ||
| - | |||
| - | <code python> | ||
| - | >>> | ||
| - | |||
| - | (' | ||
| - | |||
| - | >>> | ||
| - | |||
| - | (' | ||
| - | </ | ||
| - | |||
| - | Otr de los métodos que disponemos en la clase sockets es el que permite obtener el nombre cualificado de un domiinio: | ||
| - | |||
| - | <code python> | ||
| - | >>> | ||
| - | </ | ||
| - | |||
| - | ==== socket.gethostbyaddr(ip_address) ==== | ||
| - | |||
| - | Este método devuelve una tupla (hostname, nombre, ip_address_list) donde hostname es el nombre de host que responde a la dirección IP dada, el nombre es una lista de nombres asociados con la misma dirección& | ||
| - | |||
| - | <code python> | ||
| - | >>> | ||
| - | |||
| - | (' | ||
| - | </ | ||
| - | |||
| - | ==== socket.getservbyname(servicename [, | ||
| - | |||
| - | Este método le permite obtener el número de puerto del nombre del puerto: | ||
| - | |||
| - | <code python> | ||
| - | >>> | ||
| - | >>> | ||
| - | |||
| - | 80 | ||
| - | |||
| - | >>> | ||
| - | |||
| - | 25 | ||
| - | </ | ||
| - | |||
| - | ==== socket.getservbyport(puerto [, nombre_protocolo]) ==== | ||
| - | |||
| - | Este método realiza la operación inversa de la anterior, lo que le permite obtener el nombre del puerto a partir del número de puerto: | ||
| - | |||
| - | <code python> | ||
| - | >>> | ||
| - | |||
| - | ' | ||
| - | |||
| - | >>> | ||
| - | |||
| - | ' | ||
| - | </ | ||
| - | |||
| - | ===== Ejemplo para los métodos de socket ===== | ||
| - | |||
| - | El siguiente script es un ejemplo de cómo podemos usar estos métodos para obtener información de los servidores de Google. | ||
| - | |||
| - | Puede encontrar el siguiente código en el archivo '' | ||
| - | |||
| - | <code python> | ||
| - | # -*- encoding: utf-8 -*- | ||
| - | |||
| - | import socket | ||
| - | import sys | ||
| - | |||
| - | try: | ||
| - | print(" | ||
| - | print(socket.gethostbyname_ex(' | ||
| - | print(" | ||
| - | print(socket.gethostbyaddr(' | ||
| - | print(" | ||
| - | print(socket.getfqdn(' | ||
| - | |||
| - | except socket.error as error: | ||
| - | print (str(error)) | ||
| - | print (" | ||
| - | sys.exit() | ||
| - | </ | ||
| - | |||
| - | '' | ||
| - | |||
| - | ===== Búsqueda inversa ===== | ||
| - | |||
| - | Este comando obtiene el nombre de host de la dirección IP. Para esta tarea, podemos usar la función '' | ||
| - | |||
| - | En este script, obtenemos el nombre de host de la dirección IP de '' | ||
| - | |||
| - | Puede encontrar el siguiente código en el archivo '' | ||
| - | |||
| - | <code python> | ||
| - | # | ||
| - | # --*-- coding: UTF-8 --*-- | ||
| - | |||
| - | import sys, socket | ||
| - | try : | ||
| - | result=socket.gethostbyaddr(" | ||
| - | print(" | ||
| - | print(" | ||
| - | print(" | ||
| - | for item in result[2]: | ||
| - | print(" | ||
| - | except socket.herror as e: | ||
| - | print(" | ||
| - | </ | ||
| - | |||
| - | ===== Actividad práctica ===== | ||
| - | |||
| - | **Dado un nombre de dominio introducido por la entrada estándar por parte del usuario, obtener información relación con dicho dominio como dirección IP, host asociado y nombre cualificado del dominio.** | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | |||
| - | dominio = input() | ||
| - | |||
| - | try: | ||
| - | print(" | ||
| - | ip = socket.xxx(xxx) | ||
| - | print(ip) | ||
| - | print(" | ||
| - | print(socket.xxx(str(ip))) | ||
| - | print(" | ||
| - | print(socket.xxx(dominio)) | ||
| - | |||
| - | except socket.error as error: | ||
| - | print (str(error)) | ||
| - | print (" | ||
| - | </ | ||
| - | |||
| - | **Completar el script anterior sustituyendo las '' | ||
| - | |||
| - | Solución: | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | |||
| - | dominio = input() | ||
| - | |||
| - | try: | ||
| - | print(" | ||
| - | ip = socket.gethostbyname(dominio) | ||
| - | print(ip) | ||
| - | print(" | ||
| - | print(socket.gethostbyaddr(str(ip))) | ||
| - | print(" | ||
| - | print(socket.getfqdn(dominio)) | ||
| - | |||
| - | except socket.error as error: | ||
| - | print (str(error)) | ||
| - | print (" | ||
| - | </ | ||
| - | |||
| - | ===== Implementar en Python un escáner de puertos con sockets ===== | ||
| - | |||
| - | En esta sección revisaremos cómo podemos implementar el escaneo de puertos con sockets y cómo administrar las excepciones cuando trabajamos con sockets. | ||
| - | |||
| - | Los sockets son el bloque de construcción fundamental para las comunicaciones de red y de manera fácil podemos verificar si un puerto específico está abierto, cerrado o filtrado al llamar al método '' | ||
| - | |||
| - | ==== Método connect_ex() ==== | ||
| - | |||
| - | El método '' | ||
| - | |||
| - | Puede encontrar el siguiente código en el archivo '' | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | |||
| - | ip =' | ||
| - | portlist = [22, | ||
| - | for port in portlist: | ||
| - | sock= socket.socket(socket.AF_INET, | ||
| - | result = sock.connect_ex((ip, | ||
| - | print(port,":", | ||
| - | sock.close() | ||
| - | </ | ||
| - | |||
| - | '' | ||
| - | |||
| - | * '' | ||
| - | * '' | ||
| - | |||
| - | ==== Escáner de puertos con sockets ==== | ||
| - | |||
| - | Por ejemplo, podríamos tener una función que acepte por parámetros una IP y una lista de puertos y devuelva para cada puerto si está abierto o cerrado. | ||
| - | |||
| - | En este caso necesitamos importar los módulos '' | ||
| - | |||
| - | Puede encontrar el siguiente código en el archivo '' | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | import sys | ||
| - | |||
| - | def comprobarListaPuertos(ip, | ||
| - | try: | ||
| - | for port in portlist: | ||
| - | sock= socket.socket(socket.AF_INET, | ||
| - | sock.settimeout(5) | ||
| - | result = sock.connect_ex((ip, | ||
| - | if result == 0: | ||
| - | print (" | ||
| - | else: | ||
| - | print (" | ||
| - | sock.close() | ||
| - | except socket.error as error: | ||
| - | print (str(error)) | ||
| - | print (" | ||
| - | sys.exit() | ||
| - | |||
| - | comprobarListaPuertos(' | ||
| - | </ | ||
| - | |||
| - | Ejemplo de ejecución: | ||
| - | |||
| - | < | ||
| - | Puerto 80: | ||
| - | Puerto 8080: | ||
| - | Puerto 443: Abierto | ||
| - | Puerto 22: | ||
| - | </ | ||
| - | |||
| - | ==== Explicación función escáner de puertos ==== | ||
| - | |||
| - | La forma de ejecutar esta función es mediante la llamada: | ||
| - | |||
| - | <code python> | ||
| - | comprobarListaPuertos(dominio|direccion_ip, | ||
| - | </ | ||
| - | |||
| - | Si ejecutamos la función con una ip o nombre de dominio que no exista, nos devolverá un error de conexión junto con la excepción que ha devuelve el módulo socket al no poder resolver la dirección IP. | ||
| - | |||
| - | < | ||
| - | comprobarListaPuertos(" | ||
| - | |||
| - | [Errno 11004] getaddrinfo failed.Error de conexion | ||
| - | </ | ||
| - | |||
| - | La parte más importante de la función del ejemplo anterior la encontramos cuando comprueba si el puerto está abierto o cerrado:</ | ||
| - | |||
| - | <code python> | ||
| - | # ... | ||
| - | sock= socket.socket(socket.AF_INET, | ||
| - | sock.settimeout(5) | ||
| - | result = sock.connect_ex((ip, | ||
| - | if result == 0: | ||
| - | print (" | ||
| - | else: | ||
| - | print (" | ||
| - | sock.close() | ||
| - | </ | ||
| - | |||
| - | En el código anterior vemos cómo utilizamos el método '' | ||
| - | |||
| - | <WRAP center round todo 60%> | ||
| - | IMAAAAAAAAAAAAAAAGEN | ||
| - | </ | ||
| - | |||
| - | ==== Escáner de puertos avanzado ==== | ||
| - | |||
| - | El siguiente código de Python le permitirá escanear un host local o remoto en busca de puertos abiertos. El programa busca puertos seleccionados a partir de una determinada dirección IP introducida por el usuario y refleja los puertos abiertos de regreso al usuario. Si el puerto está cerrado, también muestra información sobre el motivo, por ejemplo, por //timeout// de la conexión. | ||
| - | |||
| - | Puede encontrar el siguiente código en el archivo '' | ||
| - | |||
| - | <code python> | ||
| - | # Escaner de puertos con sockets | ||
| - | |||
| - | # Importamos modulo socket | ||
| - | from socket import * | ||
| - | |||
| - | # Preguntamos por la IP | ||
| - | ip = input(" | ||
| - | |||
| - | # Preguntamos por el puertos | ||
| - | puerto_inicio = input(" | ||
| - | puerto_fin = input(" | ||
| - | |||
| - | print (" | ||
| - | |||
| - | #recorrer cada uno de los puertos | ||
| - | for port in range(int(puerto_inicio), | ||
| - | print (" | ||
| - | # Crea el objeto socket | ||
| - | s = socket(AF_INET, | ||
| - | s.settimeout(5) | ||
| - | |||
| - | # Comprobar conexion e imprimimos si el puerto está abierto | ||
| - | if(s.connect_ex((ip, | ||
| - | print(" | ||
| - | |||
| - | # Cierra el socket | ||
| - | s.close() | ||
| - | |||
| - | print(" | ||
| - | </ | ||
| - | |||
| - | Ejemplo de ejecución: | ||
| - | |||
| - | < | ||
| - | Introduce IP : 192.168.0.1 | ||
| - | Introduce puerto de inicio : 22 | ||
| - | Introduce puerto de fin : 80 | ||
| - | Escaneando IP 192.168.0.1 : | ||
| - | Probando puerto 22 ... | ||
| - | Probando puerto 23 ... | ||
| - | El puerto | ||
| - | Probando puerto 24 ... | ||
| - | Probando puerto 25 ... | ||
| - | (...) | ||
| - | El puerto | ||
| - | Probando puerto 54 ... | ||
| - | Probando puerto 55 ... | ||
| - | Probando puerto 56 ... | ||
| - | (...) | ||
| - | Probando puerto 71 ... | ||
| - | Probando puerto 72 ... | ||
| - | Probando puerto 73 ... | ||
| - | Probando puerto 74 ... | ||
| - | Probando puerto 75 ... | ||
| - | Probando puerto 76 ... | ||
| - | Probando puerto 77 ... | ||
| - | Probando puerto 78 ... | ||
| - | Probando puerto 79 ... | ||
| - | Escaneo finalizado! | ||
| - | </ | ||
| - | |||
| - | ==== Escáner de puertos a partir de un dominio ==== | ||
| - | |||
| - | El siguiente script de Python nos permitirá escanear una dirección IP con las funciones '' | ||
| - | |||
| - | En este script, el usuario debe ingresar como parámetros obligatorios el host y un puerto, separados por una coma: | ||
| - | |||
| - | <WRAP center round todo 60%> | ||
| - | IMAAAAAAAAAAAAAAAAAAAAGEN | ||
| - | </ | ||
| - | |||
| - | Puede encontrar el siguiente código en el archivo '' | ||
| - | |||
| - | <code python> | ||
| - | # | ||
| - | # -*- coding: utf-8 -*- | ||
| - | |||
| - | # Para jugar con los argumentos que introduce el usuario: | ||
| - | import optparse | ||
| - | |||
| - | from socket import * | ||
| - | |||
| - | # Lanzar diferentes hilos de ejecución: | ||
| - | from threading import * | ||
| - | |||
| - | def socketScan(host, | ||
| - | try: | ||
| - | socket_connect = socket(AF_INET, | ||
| - | socket_connect.settimeout(10) | ||
| - | socket_connect.connect((host, | ||
| - | print(' | ||
| - | except Exception as error: | ||
| - | print(error) | ||
| - | print(' | ||
| - | finally: | ||
| - | socket_connect.close() | ||
| - | |||
| - | def portScanning(host, | ||
| - | try: | ||
| - | ip = gethostbyname(host) | ||
| - | except: | ||
| - | print(" | ||
| - | return | ||
| - | |||
| - | try: | ||
| - | name = gethostbyaddr(ip) | ||
| - | print(' | ||
| - | except: | ||
| - | print(' | ||
| - | |||
| - | for port in ports: | ||
| - | # Usamos el módulo ' | ||
| - | # distinto para cada puerto | ||
| - | t = Thread(target=socketScan, | ||
| - | t.start() | ||
| - | |||
| - | def main(): | ||
| - | parser = optparse.OptionParser(' | ||
| - | parser.add_option(' | ||
| - | parser.add_option(' | ||
| - | |||
| - | (options, args) = parser.parse_args() | ||
| - | |||
| - | host = options.host | ||
| - | ports = str(options.port).split(',' | ||
| - | |||
| - | if (host == None) | (ports[0] == None): | ||
| - | print(parser.usage) | ||
| - | exit(0) | ||
| - | |||
| - | portScanning(host, | ||
| - | |||
| - | |||
| - | if __name__ == ' | ||
| - | main() | ||
| - | </ | ||
| - | |||
| - | ==== Función principal escáner de puertos a partir de un dominio ==== | ||
| - | |||
| - | Este podría ser nuestro programa principal donde obtenemos los parámetros obligatorios de host y puertos para la ejecución del script. Una vez que hayamos obtenido estos parámetros, | ||
| - | |||
| - | <code python> | ||
| - | def main(): | ||
| - | parser = optparse.OptionParser(' | ||
| - | parser.add_option(' | ||
| - | parser.add_option(' | ||
| - | |||
| - | (options, args) = parser.parse_args() | ||
| - | |||
| - | host = options.host | ||
| - | ports = str(options.port).split(',' | ||
| - | |||
| - | if (host == None) | (ports[0] == None): | ||
| - | print(parser.usage) | ||
| - | exit(0) | ||
| - | |||
| - | portScanning(host, | ||
| - | |||
| - | |||
| - | if __name__ == ' | ||
| - | main() | ||
| - | |||
| - | </ | ||
| - | |||
| - | Ejecución: | ||
| - | |||
| - | < | ||
| - | python socket_portScan.py -H www.google.es -P 80,21,22,23 | ||
| - | </ | ||
| - | |||
| - | En la ejecución del script anterior, podemos ver el estado de todos los puertos que están del dominio: | ||
| - | |||
| - | < | ||
| - | [+] Scan Results for: mad41s10-in-f3.1e100.net | ||
| - | [+] 80/tcp open | ||
| - | |||
| - | timed out | ||
| - | [-] 21/tcp closed | ||
| - | |||
| - | timed out | ||
| - | [-] 23/tcp closed | ||
| - | |||
| - | timed out | ||
| - | [-] 22/tcp closed | ||
| - | </ | ||
| - | |||
| - | ===== Actividad práctica ===== | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | import sys | ||
| - | |||
| - | # Preguntamos por la IP | ||
| - | ip = input(" | ||
| - | |||
| - | # | ||
| - | listaPuertos = list(int(num) for num in input(" | ||
| - | |||
| - | print (" | ||
| - | |||
| - | try: | ||
| - | for port in xxx: | ||
| - | s = socket.socket(socket.AF_INET, | ||
| - | s.settimeout(5) | ||
| - | if (s.connect_ex((xxx, | ||
| - | try: | ||
| - | serv = socket.getservbyport(xxx) | ||
| - | except socket.error: | ||
| - | error_servidor=" | ||
| - | |||
| - | print((" | ||
| - | | ||
| - | print(" | ||
| - | |||
| - | except KeyboardInterrupt as exception: | ||
| - | print(exception) | ||
| - | sys.exit() | ||
| - | </ | ||
| - | |||
| - | **Completa el siguiente script para obtener un escáner de puertos introduciendo desde teclado la IP y los puertos de inicio y fin. Sustituir las '' | ||
| - | |||
| - | Solución: | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | import sys | ||
| - | |||
| - | # Preguntamos por la IP | ||
| - | ip = input(" | ||
| - | |||
| - | # | ||
| - | listaPuertos = list(int(num) for num in input(" | ||
| - | |||
| - | puerto_inicio = listaPuertos[0] | ||
| - | puerto_fin = listaPuertos[1] | ||
| - | |||
| - | print (" | ||
| - | |||
| - | try: | ||
| - | for port in range(int(puerto_inicio), | ||
| - | s = socket.socket(socket.AF_INET, | ||
| - | s.settimeout(5) | ||
| - | if (s.connect_ex((ip, | ||
| - | try: | ||
| - | serv = socket.getservbyport(port) | ||
| - | except socket.error: | ||
| - | error_servidor=" | ||
| - | |||
| - | print((" | ||
| - | | ||
| - | print(" | ||
| - | |||
| - | except KeyboardInterrupt as exception: | ||
| - | print(exception) | ||
| - | sys.exit() | ||
| - | |||
| - | </ | ||
| - | |||
| - | ===== Implementar en Python un servidor HTTP ===== | ||
| - | |||
| - | Podríamos crear un socket del tipo TCP y vincularlo a un puerto. Podríamos utilizar " | ||
| - | |||
| - | ==== Métodos de socket del servidor ==== | ||
| - | |||
| - | Estos son los principales métodos que podemos usar desde el punto de vista del servidor: | ||
| - | |||
| - | * '' | ||
| - | * '' | ||
| - | * '' | ||
| - | ==== Implementación del servidor ==== | ||
| - | |||
| - | De los métodos comentados anteriormente podríamos utilizar el método '' | ||
| - | |||
| - | El módulo socket proporciona el método '' | ||
| - | |||
| - | Posteriormente, | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | |||
| - | mySocket = socket.socket(socket.AF_INET, | ||
| - | mySocket.bind((' | ||
| - | mySocket.listen(5) | ||
| - | |||
| - | while True: | ||
| - | print(' | ||
| - | (recvSocket, | ||
| - | print(' | ||
| - | print(recvSocket.recv(1024)) | ||
| - | recvSocket.send(bytes(" | ||
| - | recvSocket.close() | ||
| - | </ | ||
| - | |||
| - | Al ejecutar el código anterior, el script se quedará en ejecución a la espera de conexiones. | ||
| - | |||
| - | Podemos probar que funciona correctamente haciendo una petición con '' | ||
| - | |||
| - | < | ||
| - | curl localhost: | ||
| - | </ | ||
| - | |||
| - | Nos devolvería el documento HTML que indicamos en el código del servidor. | ||
| - | |||
| - | Veremos cómo implementar un cliente HTTP sencillo en Python para probar también el servidor. | ||
| - | ==== Probando el servidor creando un cliente HTTP ==== | ||
| - | |||
| - | Si queremos probar el funcionamiento del servidor HTTP, podríamos crearnos otro script que nos permite obtener la respuesta envía el servidor que hemos creado. | ||
| - | |||
| - | <code python> | ||
| - | # | ||
| - | import socket | ||
| - | webhost = ' | ||
| - | webport = 8080 | ||
| - | print(" | ||
| - | webclient = socket.socket(socket.AF_INET, | ||
| - | webclient.connect((webhost, | ||
| - | webclient.send(bytes(" | ||
| - | reply = webclient.recv(4096) | ||
| - | print(" | ||
| - | print(reply.decode()) | ||
| - | </ | ||
| - | |||
| - | Con el servidor HTTP funcionando, | ||
| - | |||
| - | < | ||
| - | Contacting localhost on port 8080 ... | ||
| - | Response from localhost: | ||
| - | HTTP/1.1 200 OK</ | ||
| - | </ | ||
| - | ==== Actividad práctica ==== | ||
| - | |||
| - | **Completa el siguiente script para implementar un servidor HTTP que esté escuchando en el puerto 8080 y acepte como máximo 5 conexiones de forma simultánea.** | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | |||
| - | # Crear un socket del tipo TCP y vincularlo a un puerto | ||
| - | # Utilizamos ' | ||
| - | # El puerto podría ser 80, pero como necesita privilegios de root, | ||
| - | # usemos uno por mayor o igual que 8080 | ||
| - | |||
| - | mySocket = socket.socket(xxx, | ||
| - | mySocket.bind((' | ||
| - | |||
| - | # Poner en cola un máximo de 5 solicitudes de conexión TCP | ||
| - | |||
| - | xxx.listen(5) | ||
| - | |||
| - | # Aceptar conexiones, leer datos entrantes y responder una página HTML (en un bucle) | ||
| - | |||
| - | while True: | ||
| - | print(' | ||
| - | (recvSocket, | ||
| - | print(' | ||
| - | print(recvSocket.xxx(1024)) | ||
| - | recvSocket.xxx(bytes(" | ||
| - | xxx.close() | ||
| - | </ | ||
| - | |||
| - | Solución: | ||
| - | |||
| - | <code python> | ||
| - | import socket | ||
| - | |||
| - | # Crear un socket del tipo TCP y vincularlo a un puerto | ||
| - | # Utilizamos ' | ||
| - | # El puerto podría ser 80, pero como necesita privilegios de root, | ||
| - | # usemos uno por mayor o igual que 8080 | ||
| - | |||
| - | mySocket = socket.socket(socket.AF_INET, | ||
| - | mySocket.bind((' | ||
| - | |||
| - | # Poner en cola un máximo de 5 solicitudes de conexión TCP | ||
| - | mySocket.listen(5) | ||
| - | |||
| - | # Aceptar conexiones, leer datos entrantes y responder una página HTML (en un bucle) | ||
| - | |||
| - | while True: | ||
| - | print(' | ||
| - | (recvSocket, | ||
| - | print(' | ||
| - | print(recvSocket.recv(1024)) | ||
| - | recvSocket.send(bytes(" | ||
| - | recvSocket.close() | ||
| - | </ | ||
| - | |||
| - | ===== Resumen ===== | ||
| - | |||
| - | En esta unidad hemos aprendido: | ||
| - | |||
| - | * Crear un socket utilizando el constructor '' | ||
| - | * Obtener información con los métodos '' | ||
| - | * Gracias al uso del método '' | ||
| - | * Implementar nuestro propio servidor HTTP que tiene la capacidad de atender peticiones por parte de '' | ||
| - | * El método '' | ||
| - | * Finalmente, implementamos un cliente HTTP para realizar peticiones al servidor creado anteriormente. | ||
| - | |||
| - | ===== FAQ ===== | ||
| - | |||
| - | ==== ¿Cuántas familias de direcciones para sockets encontramos en el módulo socket de Python? ==== | ||
| - | |||
| - | * **AF_INET**: | ||
| - | * **AF_INET6**: | ||
| - | * **AF_UNIX** o **AF_LOCAL**: | ||
| - | |||
| - | ==== ¿Cuál es la utilidad de los sockets? ==== | ||
| - | |||
| - | Los sockets **mantienen la conexión en tiempo real entre un cliente y un servidor con el objetivo de enviar y recibir datos** de un lado a otro. Por ejemplo, podremos crear nuestro propio chat; es decir, una aplicación de escritorio en nuestro ordenador recibiendo y enviando mensajes, para que el lado del servidor reciba y envíe los mensajes en tiempo real. | ||
| - | |||
| ===== Recursos ===== | ===== Recursos ===== | ||
| * [[https:// | * [[https:// | ||
| * [[https:// | * [[https:// | ||
informatica/programacion/cursos/python_avanzado_proyectos_seguridad/introduccion_sockets.1731336830.txt.gz · Última modificación: por tempwin
