Skip to content

[QUESTION] how use TransportArbitrator class in Python #386

@sfavazza

Description

@sfavazza

If you didn't find answer in existing open/closed issues you may ask here
Hello eRPC team,

I am trying to test the shared transport capability in Python, but so far I had not much success. The client hangs indefinitely at the first remote-method invocation.

CONTEXT

  • simple scenario with a single server & client, both running on the same machine
  • the TCP transport is used
  • the IDL file describe a single interface with a single method

SOURCES

IDL.erpc

program IDLProgramName

// interfaces contains list of methods a client can remotely invoke
interface DummyInterface {
    // a remotely callable method
    access_count() -> int32
}

common.py

HOST = "localhost"
PORT = 5777

multi-server.py

"""Multi client server example"""

import erpc
# --------------------------------------------------------------------------------------------------------------
# eRPC generated code (in same level folder)
from erpcservice import IDLProgramName

import common as c


class MyServiceHandler(IDLProgramName.interface.IDummyInterface):

    def __init__(self):
        self._count = 0

    # IMPORTANT: generators are not supported by the Python shim code
    # remote callable method implementation
    def access_count(self) -> int:
        """Return invocation count"""
        self._count += 1
        return self._count


# The service shall be wrapped by an instance running it (transport has to be setup).
def run_multi_client_server(transport):
    # create a service to expose and initialize it with our service handler
    service = IDLProgramName.server.DummyInterfaceService(
        MyServiceHandler()
    )

    # create a server (SimpleServer is a minimal implementation of the generic erpc.server.Server class)
    server = erpc.simple_server.SimpleServer(transport, erpc.basic_codec.BasicCodec)
    # add the generated service to the server
    server.add_service(service)
    print("\r\nStarted server...")
    server.run()


if __name__ == '__main__':
    # before starting the server let's define the transport is shall use
    transport = erpc.transport.TCPTransport(c.HOST, c.PORT, isServer=True)

    # finally run the server providing the requested transport
    try:
        run_multi_client_server(transport)
    except erpc.transport.ConnectionClosed:
        print("that's all folks!!")

multi-client.py

"""Dummy client implementation"""


import time
import erpc
import common as c
# --------------------------------------------------------------------------------------------------------------
# eRPC generated code
from erpcservice import IDLProgramName


def run_multi_client_client(transport):

    codec = erpc.basic_codec.BasicCodec
    print("arbitrator created")
    arbitrator = erpc.arbitrator.TransportArbitrator(transport, codec)
    # NOTE: provide the arbitrator as transport, to keep track of the token generated for each invocation
    client_mngr = erpc.client.ClientManager(arbitrator, codec)
    # add an arbitrator to allow multiple clients accessing it
    client_mngr.arbitrator = arbitrator

    # start the auto-generated client interface with a client-manager
    client = IDLProgramName.client.DummyInterfaceClient(client_mngr)
    print("client started")

    for _ in range(7):

        # FIXME: the client hangs here, and the server seems to not receive anything
        count = client.access_count()

        # NOTE: it seems that the connection gets closed as a natural consequence of the cleaning up task from
        # Python once it completes its execution.
        print(f"got access count {count}")


    # wait until explicitly killed
    print("quitting")


if __name__ == '__main__':
    transport = erpc.transport.TCPTransport(c.HOST, c.PORT, isServer=False)
    run_multi_client_client(transport)

ISSUE

Before attempting the arbitrated-transport approach, I successfully managed to get client & server communicating each other.

When modifying the code as above to make use of the shared-transport:

  • the server starts properly
  • but the client gets stuck at the first client.access_count() invocation
  • debugging I realized that the client gets stuck when waiting for an event from within the arbitrator client_receive method

Am I missing some steps in the shared code? Any chance to get a working Python example with an shared-transport?

Steps you didn't forgot to do

  • I checked if there is no related issue opened/closed.
  • I checked that there doesn't exist opened/closed PR which is solving this issue.
  • I looked in documentation if there is related information.
    • very scarce info about the arbitration initialiazation for the C/C++-code

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions