获取Twisted服务器的IP地址

时间:2020-07-13 04:25:04

标签: python twisted

如果我有一台Twisted服务器,如何找到其面向公众的IP地址?

以这个简单的回显服务器示例为例:

from twisted.internet import protocol, reactor, endpoints

class Echo(protocol.Protocol):
    def dataReceived(self, data):
        self.transport.write(data)

class EchoFactory(protocol.Factory):
    def buildProtocol(self, addr):
        return Echo()

server_endpoint = endpoints.serverFromString(reactor, "tcp:1234")
listening_port_deferred = server_endpoint.listen(EchoFactory())
reactor.run()

我原本期望像server_endpoint.getHost()这样的东西,但是我看不到TCP4ServerEndpoint提供了有用的东西。

通过在reactor.run()之前添加以下行,我们可以看到服务器正在侦听所有接口(0.0.0.0):

def print_host(listening_port):
    print("listening_port.getHost():", listening_port.getHost())
listening_port_deferred.addCallback(print_host)

它输出listening_port.getHost(): IPv4Address(type='TCP', host='0.0.0.0', port=1234)。但这并不能帮助我们了解服务器网络接口的IP地址。

我们可以通过添加以下内容作为buildProtocol():的第一行来获取客户端的IP地址

print("Client's address:", addr.host)

但这只会给我们客户的地址。

我应该如何获取服务器的IP地址?

2 个答案:

答案 0 :(得分:1)

Twisted会仅使用在侦听端口上找到的方法getHost告诉您将服务器绑定到的地址。不幸的是,您发现它有一个很大的限制,那就是当服务器侦听所有本地地址(INADDR_ANY)时,它会给您0.0.0.0({{1}的规范IPv4点分四进制表示形式) }。

发生这种情况时,您必须离开Twisted。我发现netifaces软件包对此非常有用。从文档中:

INADDR_ANY

通过将此信息与观察到的>>> netifaces.interfaces() ['lo0', 'gif0', 'stf0', 'en0', 'en1', 'fw0'] >>> >>> addrs = netifaces.ifaddresses('lo0') >>> addrs[netifaces.AF_INET] [{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}] 表示“所有本地地址”相结合,可以确定服务器将在其上接受连接的本地地址。

答案 1 :(得分:1)

由于臭名昭著的评论,我意识到服务器的IP地址仅在客户端连接后才可用。但是,正如让·保罗指出的那样,此IP地址不一定是面向公众的,并且很可能在NATing路由器后面。

要获取给定连接的服务器IP地址,我们可以使用Protocol类的getHost()属性中的transport方法。在ITransport界面中对此进行了记录。

例如,如果我们将以下方法添加到原始问题的Echo协议类中,则每次客户端连接时,服务器都会打印出使用的IP地址。

def connectionMade(self):
    print("IP address of host given connection:", self.transport.getHost())

例如,如果从运行服务器的同一台计算机进行连接,则会看到:

IP address of host given connection: IPv4Address(type='TCP', host='127.0.0.1', port=1234)

但是,如果您从同一网络上的另一台计算机进行连接,则可能会看到:

IP address of host given connection: IPv4Address(type='TCP', host='192.168.5.103', port=1234)