Почему pyro4 не может найти сервер имен под 127.0.1.1, но успешно с 127.0.0.1?
Я пытаюсь запустить сервер pyro4 с пользовательским циклом событий на Raspberry Pi с Raspbian 8 (Джесси). Когда я создаю сервер имен, используя имя хоста, полученное из socket.gethostname(), в частности, "raspberrypi", мой клиентский скрипт не может найти сервер имен. Когда я использую localhost в качестве имени хоста, мой клиентский скрипт может найти имя хоста. В /etc/hosts 'raspberrypi' связан с 127.0.1.1, в то время как 'localhost' явно связан с 127.0.0.1. Я думал, что оба эти адреса связаны с интерфейсом обратной связи, поэтому я не понимаю, почему один должен работать, а другой нет.
Для чего стоит, после некоторого копания в коде pyro4, это выглядит как на l.463 Pyro4.naming.py, вызов proxy.ping() завершается неудачно с 127.0.1.1, но не с 127.0.0.1, и это в конечном итоге, что вызывает сбой с прежним адресом. Не будучи экспертом в Pyro, не ясно, ожидается ли такое поведение. Какие-нибудь мысли? Я предполагаю, что это должно быть распространенной проблемой, потому что большинство (всех?) Разновидностей Debian содержат отдельные строки в /etc/hosts для этих двух адресов.
Я приложил код ниже, который воспроизводит проблему. По сути, это всего лишь слегка измененная версия примера "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 ответ
Поиск по имени сервера Pyro основан на двух вещах:
- просмотр трансляции
- прямой поиск по имени хоста /ip-адресу
Первый недоступен, когда вы используете адаптер обратной петли для привязки сервера имен (петлевая петля не поддерживает широковещательные сокеты). Итак, мы остались со вторым. Тогда ответ на ваш вопрос прост: прямой поиск выполняется по значению элемента конфигурации NS_HOST, который по умолчанию имеет значение "localhost". Когда localhost разрешается до 127.0.0.1, он никогда не подключится к 127.0.1.1.
Предложение: привяжите сервер имен на 0.0.0.0 или "" (пустое имя хоста), и он также должен иметь возможность запустить широковещательный ответчик. Тогда у ваших клиентов не возникнет проблем с его поиском.
В качестве альтернативы, просто установите NS_HOST на 127.0.1.1 (или имя хоста вашего ящика) для ваших клиентов, и они также смогут найти сервер имен, если он связан с 127.0.1.1