pythonraspberry-pipyro4

Pyro4 [Errno -2]


I am trying out pyro4 connection between my PC and Raspberry Pi 4.
Code on my PC is:

# saved as server.py
import Pyro4, Pyro4.naming
import socket, threading

# Define an object that will be accessible over the network.
# This is where all your code should go...
@Pyro4.expose
class MessageServer(object):
    def show_message(self, msg):
        print("Message received: {}".format(msg))


# Start a Pyro nameserver and daemon (server process) that are accessible
# over the network. This has security risks; see
# https://pyro4.readthedocs.io/en/stable/security.html
hostname = socket.gethostname()
ns_thread = threading.Thread(
    target=Pyro4.naming.startNSloop, kwargs={'host': hostname}
)
ns_thread.daemon = True   # automatically exit when main program finishes
ns_thread.start()
main_daemon = Pyro4.Daemon(host=hostname)

# find the name server
ns = Pyro4.locateNS()
# register the message server as a Pyro object
main_daemon_uri = main_daemon.register(MessageServer)
# register a name for the object in the name server
ns.register("example.message", main_daemon_uri)

# start the event loop of the main_daemon to wait for calls
print("Message server ready.")
main_daemon.requestLoop()

And code on my Raspberry is:

import Pyro4
import sys

print("Message:")
msg=sys.stdin.readline().strip()

message_server = Pyro4.Proxy("PYRONAME:192.168.1.5")
message_server.show_message(msg)

Code on my PC doesn t show any errors, but when I try to send a message from raspberry i get this:

What s your message?
test
Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 102, in getIpAddress
    return getaddr(config.PREFER_IP_VERSION) if ipVersion is None else getaddr(ipVersion)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
    ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
  File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 515, in connect_and_handshake
    sslContext=sslContext)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 266, in createSocket
    if getIpVersion(connect[0]) == 4:
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 68, in getIpVersion
    address = getIpAddress(hostnameOrAddress)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 106, in getIpAddress
    return getaddr(0)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/socketutil.py", line 94, in getaddr
    ip = socket.getaddrinfo(hostname or socket.gethostname(), 80, family, socket.SOCK_STREAM, socket.SOL_TCP)[0][4][0]
  File "/usr/lib/python3.7/socket.py", line 748, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/pi/Desktop/client.py", line 10, in <module>
    message_server.show_message(msg)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
    self._pyroGetMetadata()
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
    self.__pyroCreateConnection()
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 588, in __pyroCreateConnection
    uri = _resolve(self._pyroUri, self._pyroHmacKey)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 1915, in _resolve
    return nameserver.lookup(uri.object)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 275, in __getattr__
    self._pyroGetMetadata()
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 615, in _pyroGetMetadata
    self.__pyroCreateConnection()
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 596, in __pyroCreateConnection
    connect_and_handshake(conn)
  File "/home/pi/.local/lib/python3.7/site-packages/Pyro4/core.py", line 549, in connect_and_handshake
    raise ce
Pyro4.errors.CommunicationError: cannot connect to ('JAKOB-PC', 9090): [Errno -2] Name or service not known

My PC has its firewall disabled, so there shouldn t be any problem with that. My local ip is 192.168.1.5. I am using a headless Raspberry and write code on it with puTTY and VNC.

I have googled this error but couldn t find any answers. Any help would be appreciated.


Solution

  • In short I couldn't solve the problem with Pyro and (almost) no one helped so I decided to use 'websockets' instead.

    You can read the documentation here but I'll explain it here anyway.

    First of all you need two devices with network connection. You also have to run python 3.6.1 on both of them. After that you also need to install websockets if you don't have them already with pip install websockets or as I had to do it with pip3 install websockets.

    Code below runs on the server and handles messages you send to it from client. Function 'hello' is a simple example of processing request and sending back a response. 'request' is the data server receives, that data must be bytes, string on iterable. Response is made by converting request to integer, squaring it and converting it back to string. This response is then sent back to client. 'start_server' defines the server, function that will define its behavior(hello), ip address on witch the server is running on(192.168.1.117) and port on witch it will receive requests(8765).

    !/usr/bin/env python
    
    import asyncio
    import websockets
    
    print("Running...")
    
    async def hello(websocket, path):
        request = await websocket.recv()
        print("Request: " + request)
    
        response = str(int(request)*int(request))
    
        await websocket.send(response)
        print("Response:" + response)
    
    start_server = websockets.serve(hello, "192.168.1.117", 8765)
    
    asyncio.get_event_loop().run_until_complete(start_server)
    asyncio.get_event_loop().run_forever()
    

    Next bit is code on the client. 'uri' is ip and port of the server. Function 'tellServ' asks you to input some data('tell' variable) and sends it to the server. After that it waits for reply and once it gets it it prints it out. In this case if I would input number "6" server would reply with "36". Function loop is in a while loop so I can send multiple numbers without having to restart the script.

    #!/usr/bin/env python
    
    import asyncio
    import websockets
    
    uri = "ws://192.168.1.117:8765"
    
    async def tellServ():
        async with websockets.connect(uri) as websocket:
            tell = input("Podatek ki ga posles: ")
            await websocket.send(tell)
    
            reply = await websocket.recv()
            print("Odgovor:")
            print(reply)
    while 1:
        asyncio.get_event_loop().run_until_complete(tellServ())