twisted - 获取OS选择的监听端口

时间:2011-08-15 19:49:38

标签: python tcp twisted p2p

我正在使用应用程序框架编写一个扭曲的P2P客户端。传入连接的侦听端口将位于随机(OS确定)端口上。但是,我需要一种方法来确定创建它后端口是什么:

import twisted... etc.

application = service.Application('vmesh')
peerservice = MyPeerService()
servicecollection = service.IServiceCollection(application)
factory = MyPeerFactory(peerservice)
server = internet.TCPServer(0, factory) # listen on random port
listen_port = server.getHost().port # ??? doesn't work...
server.setServiceParent(servicecollection)

我在文档中找不到有关查询由internet.TCPServer()创建的端口或由reactor.listenTCP()转发的端口的内容。我不能简单地等待连接发生,因为客户端必须宣布其端口才能实现这些连接。

3 个答案:

答案 0 :(得分:20)

listenTCP会返回IListeningPort,其getHost()方法会返回一个port的对象。例如:

>>> from twisted.internet import reactor
>>> from twisted.internet.protocol import Factory
>>> port = reactor.listenTCP(0, Factory())
>>> port.getHost().port
55791

但是,TCPServerprivilegedStartService启动之前不会调用listenTCP。另外,IListeningPort实际上并未通过公共API公开。因此,您需要编写自己的Service。幸运的是,这很容易做到; TCPServer做得不多。您只需要编写一个在开始侦听时立即报告其端口的端口。这是一个例子:

from twisted.internet import reactor
from twisted.application.service import Service

class PortReporter(Service, object):
    def __init__(self, factory, reportPort):
        self.factory = factory
        self.reportPort = reportPort

    def privilegedStartService(self):
        self.listeningPort = reactor.listenTCP(0, self.factory)
        self.reportPort(self.listeningPort.getHost().port)
        return super(PortReporter, self).privilegedStartService()

    def stopService(self):
        self.listeningPort.stopListening()
        return super(PortReporter, self).stopService()

然后您可以在tac文件中使用它,如下所示:

from twisted.internet.protocol import Factory
from twisted.application.service import Application
application = Application("test")
def showPortNumber(n):
    print("The port number is: %d" % (n,))
PortReporter(Factory(), showPortNumber).setServiceParent(application)

答案 1 :(得分:0)

如果您尚未启动服务器(尚未调用startService),您可以访问绑定到服务器的端口:

>>> serv._getPort()._realPortNumber

否则你也可以这样做:

>>> serv._port._realPortNumber

答案 2 :(得分:0)

FWIW如果你需要在这里使用端点这是我的实现,我的本地设置略有调整(回调选项在这里也可以正常工作):

class PortReporter(StreamServerEndpointService, object):
    def __init__(self, endpoint, factory):
        StreamServerEndpointService.__init__(self, endpoint, factory)
    self._reportedPort = None

def privilegedStartService(self):
    r = super(PortReporter, self).privilegedStartService()
    self._waitingForPort.addCallback(self.port_cb)
    return r

def port_cb(self, port):
    self._reportedPort = port.getHost().port
    return port

def getReportedPort(self):
    return self._reportedPort