2009-04-22 33 views
16

Actualmente estoy escribiendo un servidor telnet en Python. Es un servidor de contenido. Las personas se conectaban al servidor a través de telnet y se les presentaba contenido de solo texto.Múltiples conexiones de red simultáneas - servidor Telnet, Python

Mi problema es que el servidor obviamente necesitaría soportar más de una conexión simultánea. La implementación actual que ahora tengo solo admite una.

Este es el, servidor de base de prueba de concepto que empecé con (mientras que el programa ha cambiado mucho con el tiempo, el marco básico de telnet no tiene):

import socket, os 

class Server: 
    def __init__(self): 
     self.host, self.port = 'localhost', 50000 
     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
     self.socket.bind((self.host, self.port)) 

    def send(self, msg): 
     if type(msg) == str: self.conn.send(msg + end) 
     elif type(msg) == list or tuple: self.conn.send('\n'.join(msg) + end) 

    def recv(self): 
     self.conn.recv(4096).strip() 

    def exit(self): 
     self.send('Disconnecting you...'); self.conn.close(); self.run() 
     # closing a connection, opening a new one 

    # main runtime 
    def run(self): 
     self.socket.listen(1) 
     self.conn, self.addr = self.socket.accept() 
     # there would be more activity here 
     # i.e.: sending things to the connection we just made 


S = Server() 
S.run() 

Gracias por su ayuda.

Respuesta

4

Necesita alguna forma de socket asíncrono IO. Eche un vistazo a this explanation, que analiza el concepto en términos de socket de bajo nivel, y los ejemplos relacionados que se implementan en Python. Eso debería apuntarle en la dirección correcta.

3

Para una muy fácil victoria que implementar la solución usando SocketServer & la SocketServer.ThreadingMixIn

tiene un servidor de eco este ejemplo se ve bastante similar a lo que está haciendo de todos modos a ver: http://www.oreillynet.com/onlamp/blog/2007/12/pymotw_socketserver.html

+1

-1: SocketServer usa un hilo por conexión que es un enfoque realmente malo. – nosklo

+0

Sí, está en lo cierto, una vez hice un servidor xmlrpc con el que se hablaba excel mediante funciones vba que llamaban al servicio xmlrpc. Funcionó bien hasta que alguien llenó una fórmula de alrededor de 1000 filas en cuyo punto la función definida que llamó a mi servicio xmlrpc 1000 veces, la creación de 1000 hilos. No es divertido. El enfoque retorcido es sin duda el camino a seguir. – Ravi

16

Implementado en twisted:

from twisted.internet.protocol import Factory, Protocol 
from twisted.internet import reactor 

class SendContent(Protocol): 
    def connectionMade(self): 
     self.transport.write(self.factory.text) 
     self.transport.loseConnection() 

class SendContentFactory(Factory): 
    protocol = SendContent 
    def __init__(self, text=None): 
     if text is None: 
      text = """Hello, how are you my friend? Feeling fine? Good!""" 
     self.text = text 

reactor.listenTCP(50000, SendContentFactory()) 
reactor.run() 

Pruebas:

$ telnet localhost 50000 
Trying 127.0.0.1... 
Connected to localhost. 
Escape character is '^]'. 
Hello, how are you my friend? Feeling fine? Good! 
Connection closed by foreign host. 

En serio, cuando se trata de red asíncrona, retorcido es el camino a seguir. Maneja conexiones múltiples en un enfoque de proceso único de un solo hilo.

+1

Esto es perfecto. ¿Podría dar un ejemplo de envío y recepción de datos del cliente? Estoy leyendo Twisted pero es bastante detallado en sus tutoriales. – SpleenTea

+1

@SpleenTea: Simplemente agregue un método dataReceived en el protocolo y los datos irán a él. Si su protocolo está basado en línea, puede que desee subclasificar twisted.protocols.basic.LineReceiver en lugar de Protocol, por lo que solo puede definir lineReceived y se le llamará por cada línea que obtenga del cliente. Para enviar solo use self.transport.write como lo hice en el ejemplo anterior. http://twistedmatrix.com/projects/core/documentation/howto/ es muy útil, especialmente los tutoriales. – nosklo

1

Si quieres hacerlo en python puro (sans-twisted), necesitas hacer algunos subprocesos. Si havnt visto antes, echa un vistazo a: http://heather.cs.ucdavis.edu/~matloff/Python/PyThreads.pdf

alrededor de 5/6 página es un ejemplo de que es muy relevante;)

+0

-1: el artículo es un artículo general sobre hilos. Los ejemplos no tienen nada que ver con los sockets. Implementar un buen servidor de socket con subprocesos es complicado, tiene muchos detalles y es difícil de depurar, y no obtiene ningún beneficio. No hay razón para no ir asincrónico. – nosklo

+1

La parte inferior de la p.5 (srvr.py) es un servidor que usa la interfaz de socket para enlazar a un puerto y escuchar las conexiones. Tienes razón. No tiene nada que ver con la discusión actual de los enchufes. Mi error. – Alex

1

En primer lugar, la compra de libros de Comer en TCP/IP programming.

En esos libros, Comer proporcionará varios algoritmos alternativos para servidores. Hay dos enfoques estándar.

  • Tema por solicitud.

  • Proceso por solicitud.

Debe elegir uno de estos dos e implementarlo.

En thread-per, cada sesión de telnet es una hebra separada en su aplicación general.

En proceso, se bifurca cada sesión de telnet en un subproceso independiente.

Encontrará que el proceso por solicitud es mucho, mucho más fácil de manejar en Python, y generalmente hace un uso más eficiente de su sistema.

Thread-per-request está bien para cosas que van y vienen rápidamente (como solicitudes HTTP). Telnet tiene sesiones de larga duración donde el costo inicial de un subproceso no domina el rendimiento.

+0

-1: tanto el subproceso por solicitud como el proceso por solicitud no se pueden escalar a un cierto número de solicitudes simultáneas. – nosklo

+2

@nosklo: "algún número" Nada puede escalar a algunos números porque son muy grandes. El hilo por solicitud a menudo se considera bastante escalable. ¿Tiene detalles sobre cuáles son las alternativas? –

+0

no relacione su modelo de simultaneidad con cada solicitud. En su lugar, ejecute una cantidad de procesos/hilos independientes del número de solicitudes. Trate con muchas solicitudes en el mismo proceso/subproceso, preferentemente mediante el uso de async IO. Eso se escala mucho mejor. – nosklo

4

Tarde para la respuesta, pero con las únicas respuestas Twisted o hilos (ouch), quería agregar una respuesta para MiniBoa.

http://code.google.com/p/miniboa/

Twisted es grande, pero es un lugar animal grande que puede no ser la mejor introducción a la programación Telnet asíncrona de un solo subproceso. MiniBoa es una implementación de Python Telnet liviana y asíncrona de un solo hilo, diseñada originalmente para lodos, que se ajusta perfectamente a la pregunta del OP.

1

Pruebe el servidor de MiniBoa? Tiene exactamente 0 dependencias, sin retorcimientos u otras cosas necesarias. MiniBoa es un servidor de telnet asíncrono sin bloqueo, de un solo hilo, exactamente lo que necesita.

http://code.google.com/p/miniboa/

1

Uso de roscado y luego agregar el controlador en una función. El hilo llamará cada vez que una solicitud que hice:

Mira esta

import socket    # Import socket module 
import pygame 
import thread 
import threading,sys 

s = socket.socket()   # Create a socket object 
host = socket.gethostname() # Get local machine name 
port = 12345    # Reserve a port for your service. 
s.bind((host, port)) 
print ((host, port)) 
name = "" 
users = [] 

def connection_handler (c, addr): 
     print "conn handle" 
     a = c.recv (1024) 
     if a == "c": 
     b = c.recv (1024) 
     if a == "o": 
     c.send (str(users)) 
     a = c.recv (1024) 
     if a == "c": 
      b = c.recv (1024) 
     print a,b 






s.listen(6)     # Now wait for client connection. 
while True: 
    c, addr = s.accept() 
    print 'Connect atempt from:', addr[0] 
    username = c.recv(1024) 
    print "2" 
    if username == "END_SERVER_RUBBISH101": 
     if addr[0] == "192.168.1.68": 
     break 
    users.append(username) 
    thread.start_new_thread (connection_handler, (c, addr)) #New thread for connection 

print 
s.close() 
Cuestiones relacionadas