我正在尝试在运行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
答案 0 :(得分:0)
Pyro的名称服务器查找依赖于两件事:
当您使用环回适配器绑定名称服务器时,第一个不可用(环回不支持广播套接字)。所以我们留下了第二个。 您的问题的答案很简单:直接查找是在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上,他们应该能够找到名称服务器