2016-07-03 5 views
1

Я пытаюсь запустить pyro4-сервер с настраиваемым циклом событий на Raspberry Pi, запускающем Raspbian 8 (jessie). Когда я создаю сервер имен, используя имя хоста, полученное из socket.gethostname(), в частности «raspberrypi», мой клиентский скрипт не может найти сервер имен. Когда я использую «localhost» в качестве имени хоста, мой клиентский скрипт может найти имя хоста. В/etc/hosts «raspberrypi» привязан к 127.0.1.1, а «localhost», очевидно, привязан к 127.0.0.1. Я думал, что оба этих адреса связаны с интерфейсом loopback, поэтому я не понимаю, почему нужно работать, а не другого.Почему pyro4 не удается найти сервер имен в 127.0.1.1, но преуспеть с 127.0.0.1?

Для чего это стоит, после некоторого копания в коде pyro4, это похоже на l.463 файла Pyro4.naming.py, вызов toproxy.ping() завершается с 127.0.1.1, но не с 127.0.0.1 , и это в конечном счете то, что вызывает неудачу с прежним адресом. Не будучи экспертом в Pyro, неясно, будет ли такое поведение ожидаться. Есть предположения? Я предполагаю, что это должна быть распространенная проблема, потому что большинство (все?) Вкусов Debian включают отдельные строки в/etc/hosts для этих двух адресов.

Я добавил код ниже, который воспроизводит проблему. Это в основном просто слегка измененная версия примера eventloop, который поставляется с pyro.

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
поиск сервера имен

поджигателя зависит от двух вещей:

  • широковещательного поиск
  • прямого поиска по имени хоста/IP-адрес

Первый не доступен, если вы используете адаптер замыкания на себя, чтобы связать сервер имен на (loopback не поддерживает широковещательные сокеты). Итак, у нас осталось второе. Ответ на ваш вопрос прост: прямой поиск выполняется по значению элемента конфигурации 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