Python: прослушивание двух портов - PullRequest
5 голосов
/ 07 сентября 2010
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)

По сути, у меня есть этот код. Я пытаюсь прослушать два порта: 1433 и 9999. Но, похоже, это не работает.

Как я могу прослушивать два порта в одном и том же скрипте Python ??

Ответы [ 2 ]

11 голосов
/ 07 сентября 2010

Необычный способ сделать это, если вы хотите использовать Python std-lib, состоит в том, чтобы использовать SocketServer с ThreadingMixin - хотя предложение 'select', вероятно, является более эффективным.

Несмотря на то, что мы определяем только один ThreadedTCPRequestHandler, вы можете легко переназначить его так, чтобы у каждого слушателя был свой уникальный обработчик, и было бы довольно просто обернуть создание сервера / потока в один метод, если это такая вещьтебе нравится.

#!/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)
4 голосов
/ 07 сентября 2010

Пока что код в порядке (за исключением того, что отставание в 1 кажется чрезмерно строгим), проблема, конечно же, возникает, когда вы пытаетесь accept установить соединение на любом прослушивающем сокете, поскольку accept обычно является блокирующим вызовом (и «опрос» при попытке принять с короткими тайм-аутами на любом из сокетов поочередно сожжет машинные циклы до бесполезной цели).

выберите , чтобы спасти! -) select.select (или на более совершенных ОС select.poll или даже select.epoll или select.kqueue ... но, старый добрый select.select работает везде! -) сообщит, какой сокет готов и когда, так что вы можете accept соответственно. Кроме того, asyncore и asynchat обеспечивают немного больше организации (и сторонняя структура twisted, конечно, добавляет lot с такой "асинхронной" функциональностью).

В качестве альтернативы, вы можете посвятить отдельные потоки обслуживанию двух сокетов прослушивания, но в этом случае, если функциональность разных сокетов должна влиять на одни и те же общие структуры данных, координация (блокировка и с) может стать щекотливой. Я бы, конечно, рекомендовал сначала попробовать асинхронный подход - он на самом деле проще, а также предлагает потенциал для значительно лучшей производительности! -)

...