Почему 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

Другие вопросы по тегам