为什么pyro4无法在127.0.1.1下找到名称服务器但在127.0.0.1下成功?

时间:2016-07-03 19:58:42

标签: python pyro

我正在尝试在运行Raspbian 8(jessie)的Raspberry Pi上运行带有自定义事件循环的pyro4服务器。当我使用从socket.gethostname()获得的主机名创建名称服务器时,特别是'raspberrypi',我的客户端脚本找不到名称服务器。当我使用'localhost'作为主机名时,我的客户端脚本能够找到主机名。在/ etc / hosts中,'raspberrypi'绑定到127.0.1.1,而'localhost'显然绑定到127.0.0.1。我原以为这两个地址都绑定到了loopback接口,所以我不明白为什么一个应该工作而不是另一个。

值得一提的是,经过pyro4代码的挖掘后,看起来好像是pyro4.naming.py的l.463,对proxy.ping()的调用失败了127.0.1.1而不是127.0.0.1,这最终会触发前一个地址的失败。不是Pyro的专家,不清楚这种行为是否是预期的。有什么想法吗?我认为这一定是一个常见问题,因为Debian的大多数(全部?)风格在/ etc / hosts中包含这两个地址的单独行。

我在下面附上了重现问题的代码。这基本上只是pyro附带的“eventloop”示例的略微修改版本。

server.py:

import socket
import select
import sys
import Pyro4.core
import Pyro4.naming

import MotorControl

Pyro4.config.SERVERTYPE="thread"
hostname=socket.gethostname()

print("initializing services... servertype=%s" % Pyro4.config.SERVERTYPE)
# start a name server with broadcast server as well
nameserverUri, nameserverDaemon, broadcastServer = Pyro4.naming.startNS(host=hostname)
pyrodaemon=Pyro4.core.Daemon(host=hostname)

motorcontroller = MotorControl.MotorControl()
serveruri=pyrodaemon.register(motorcontroller)
nameserverDaemon.nameserver.register("example.embedded.server",serveruri)

# below is our custom event loop.
while True:
    nameserverSockets = set(nameserverDaemon.sockets)
    pyroSockets = set(pyrodaemon.sockets)
    rs = []
    rs.extend(nameserverSockets)
    rs.extend(pyroSockets)

    rs,_,_ = select.select(rs,[],[], 0.001)

    eventsForNameserver=[]
    eventsForDaemon=[]
    for s in rs:
        if s in nameserverSockets:
            eventsForNameserver.append(s)
        elif s in pyroSockets:
            eventsForDaemon.append(s)
    if eventsForNameserver:
        nameserverDaemon.events(eventsForNameserver)
    if eventsForDaemon:
        pyrodaemon.events(eventsForDaemon)

    motorcontroller.increment_count()

nameserverDaemon.close()
broadcastServer.close()
pyrodaemon.close()

client.py:

from __future__ import print_function
import Pyro4

proxy=Pyro4.core.Proxy("PYRONAME:example.embedded.server")
print("count = %d" % proxy.get_count())

MotorControl.py

class MotorControl(object):
    def __init__(self):
        self.switches = 0

    def get_count(self):
        return self.switches

    def increment_count(self):
        self.switches = self.switches + 1

错误:

Traceback (most recent call last):
  File "pyroclient.py", line 5, in <module>
    print("count = %d" % proxy.get_count())
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/core.py", line 248, in __getattr__
    self._pyroGetMetadata()
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/core.py", line 548, in _pyroGetMetadata
    self.__pyroCreateConnection()
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/core.py", line 456, in __pyroCreateConnection
    uri = resolve(self._pyroUri, self._pyroHmacKey)
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/naming.py", line 548, in resolve
    nameserver = locateNS(uri.host, uri.port, hmac_key=hmac_key)
  File "/usr/local/lib/python2.7/dist-packages/Pyro4/naming.py", line 528, in locateNS
    raise e
Pyro4.errors.NamingError: Failed to locate the nameserver

1 个答案:

答案 0 :(得分:0)

Pyro的名称服务器查找依赖于两件事:

  • 广播查询
  • 通过hostname / ip-address直接查找

当您使用环回适配器绑定名称服务器时,第一个不可用(环回不支持广播套接字)。所以我们留下了第二个。 您的问题的答案很简单:直接查找是在NS_HOST配置项的值上完成的,默认设置为&#39; localhost&#39;。当localhost解析为127.0.0.1时,它永远不会连接到127.0.1.1。

建议:将名称服务器绑定在0.0.0.0或&#34;&#34; (空主机名),它也应该能够启动广播响应器。然后您的客户在找到它时没有任何问题。

或者,只需为您的客户端设置NS_HOST为127.0.1.1(或您的盒子的主机名),如果它绑定在127.0.1.1上,他们应该能够找到名称服务器