1

There is plenty of information and examples when it comes to connecting to one server with multiple clients. But I was wondering is there a way for one client to connect to two servers at the same time? Here is my situation:

I have a python client that brings data from one server, analyzes it and sends an appropriate command to another server. There seems to be less information on this issue, If I may call it.

Here is how I tried approaching the issue. First, I made a socketio.Client class, which would enable me to create two client instances. It did not work. What am I missing here?:

import socketio

class SocketClient(socketio.Client):
    def __init__(self, server_ip):
        self.server_ip = server_ip    # server's ip address
        self.sio = socketio.Client(logger=True)

    def connect(self):
        self.sio.connect(self.server_ip, namespaces=['/my_namespace'])

    @self.sio.event
    def connect_error(self, error):
        print('connection error=> ', error)

    @self.sio.event
    def my_event(self, server_response):
        # Here I have to take the server_response 
        # and send it to another server.
        # How do I do it?
        # self.sio.emit('some_event', server_response)
        # that does not work, as I do not have the second client instance

        pass

    @self.sio.event
    def my_other_event(self, server_response):
        # process the response
        pass


# initiate the two client instances:
if __name__ == '__main__':
    first_client = SocketClient('http://192.168.100.103')
    second_client = SocketClient('http://192.168.100.104')
    first_client.connect()
    second_client.connect()

after my first try did not work, I ditched the class-instance approach and went for functional one:


import socketio

first_client = socketio.Client()
second_client = socketio.Client()


@second_client.event
@first_client.event
def connect():
    print(f'connected with id {first_client.sid}')

@second_client.event
@first_client.event
def connect_error(e):
    print('Error=> ', e)


@second_client.event
@first_client.event
def disconnect():
    print('disconnected')


@first_client.event
def my_event(server_response):
    # Here I have to take the server_response 
    # and send it to another server.
    second_client.emit('some_event', server_response)   # is it even possible?
    


@second_client.event
def my_other_event(server_response):
    # handle the response
    pass

if __name__ == '__main__':
    first_client.connect('http://192.168.100.103')
    second_client.connect('http://192.168.100.104')

In both cases, I am technically creating two clients. I might as well make them into separate files like first_client.py and second_client.py.

See where I am going with this? The goal is to get the data from server one, process it and send it to the other server with ideally one client. Please forgive me if I am missing something very obvious here. Any help is much appreciated.

P.S. both servers are up and running without any problem.

Beki
  • 1,344
  • 1
  • 12
  • 22
  • 1
    I am having a similar problem, or rather, I think we are both working toward similar goals, wanting to create one entity holding multiple socketio clients in parallel. So far I haven't found any obvious solution and I asked my own question about it: https://stackoverflow.com/questions/68973680/python-how-do-you-prevent-an-instance-using-a-socketio-asyncclient-code-from-bl Have you had any luck in the meantime? – manu3d Aug 29 '21 at 14:17

1 Answers1

2

I am using NameSpace to solve this problem.

first make a Namespace class

class MyCustomNamespace(socketio.AsyncClientNamespace):
    async def on_connect(self):
        print("I'm connected!")

    async def on_disconnect(self):
        print("I'm disconnected!")

    async def on_my_event(self, data):
        await self.emit('my_response', data)

    async def on_message(self, data):
        print("[echo]:", data)

class mysio:
    
    def __init__(self) -> None:
        global sio
        self.sio = socketio.AsyncClient(logger=False, engineio_logger=False)
        self.sio.register_namespace(MyCustomNamespace('/')) # bind

then make 2 clients. since wait() will block the process, I use create_task().

async def main():

    async def fun1():
        sio1 = mysio().sio
        await sio1.connect('http://192.168.3.85:11451')
        await sio1.emit('message', b'11111110001')
        await sio1.wait()

    async def fun2():
        sio2 = mysio().sio
        await sio2.connect('http://localhost:8080')
        await sio2.emit('message', 'from sio2')
        await sio2.wait()

    tasks = [asyncio.create_task(fun1()),asyncio.create_task(fun2()) ]
    await asyncio.wait(tasks)

asyncio.run(main())
zgxkbtl
  • 36
  • 4