2010-09-07 10 views
5
import socket 
backlog = 1 #Number of queues 

sk_1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sk_2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 

local = {"port":1433} 
internet = {"port":9999} 

sk_1.bind (('', internet["port"])) 
sk_1.listen(backlog) 

sk_2.bind (('', local["port"])) 
sk_2.listen(backlog) 

Básicamente, tengo este código. Estoy tratando de escuchar en dos puertos: 1433 y 9999. Pero esto parece no funcionar.Python: Escuche en dos puertos

¿Cómo puedo escuchar en dos puertos dentro del mismo script de python?

Respuesta

4

El código hasta ahora está bien, hasta donde llega (excepto que una acumulación de 1 parece excesivamente estricta), el problema por supuesto viene cuando intentas accept una conexión en cualquiera de las tomas, ya que accept es normalmente un bloqueo de llamada (y "sondeo" al intentar aceptar con tiempos de espera cortos en cualquiera de los zócalos alternativamente quemará los ciclos de la máquina sin un buen propósito).

select al rescate! -) select.select (o en el mejor SO select.poll o incluso select.epoll o select.kqueue ... pero, buenos viejos select.select funciona en todas partes! -) le permitirá saber qué socket está listo y cuando, por lo que puede accept apropiadamente. En esta línea, asyncore y asynchat proporcionan un poco más de organización (y un marco de terceros twisted, por supuesto, agrega un lote de dicha funcionalidad "asincrónica").

Como alternativa, puede dedicar subprocesos separados al servicio de los dos sockets de escucha, pero en este caso, si la funcionalidad de los diferentes sockets necesita afectar las mismas estructuras de datos compartidas, la coordinación (bloqueo & c) puede ponerse delicada. Sin duda, recomendaría probar primero el enfoque asincrónico: ¡es más simple, y ofrece un rendimiento sustancialmente mejor! -)

+0

Pero, la parte que no funciona es las dos ataduras. – mRt

+0

@mRt, ¿qué síntomas está observando con las llamadas 'bind'? Parecen correctos para unir los dos puertos en todas las interfaces disponibles (eso es lo que significa el "host" de cadena vacía, por supuesto). –

10

La forma elegante de hacer esto si quiere usar Python std-lib sería usar SocketServer con ThreadingMixin, aunque la sugerencia 'select' es probablemente la más eficiente.

Aunque solo definimos un ThreadedTCPRequestHandler, puede reutilizarlo fácilmente de modo que cada oyente tenga su propio manejador único y sería bastante trivial envolver la creación de servidor/subproceso en un solo método si ese es el tipo de cosa que le gusta .

#!/usr/bin/python 

import threading 
import time 
import SocketServer 

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): 

    def handle(self): 
     self.data = self.request.recv(1024).strip() 
     print "%s wrote: " % self.client_address[0] 
     print self.data 
     self.request.send(self.data.upper()) 

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 
    pass 

if __name__ == "__main__": 

    HOST = '' 
    PORT_A = 9999 
    PORT_B = 9876 

    server_A = ThreadedTCPServer((HOST, PORT_A), ThreadedTCPRequestHandler) 
    server_B = ThreadedTCPServer((HOST, PORT_B), ThreadedTCPRequestHandler) 

    server_A_thread = threading.Thread(target=server_A.serve_forever) 
    server_B_thread = threading.Thread(target=server_B.serve_forever) 

    server_A_thread.setDaemon(True) 
    server_B_thread.setDaemon(True) 

    server_A_thread.start() 
    server_B_thread.start() 

    while 1: 
     time.sleep(1) 
Cuestiones relacionadas