Question

I have the example echo server

import asyncio

class EchoServer(asyncio.Protocol):
    def connection_made(self, transport):
        peername = transport.get_extra_info('peername')
        print('connection from {}'.format(peername))
        self.transport = transport

    def data_received(self, data):
        self.transport.write(data)
        # Client piece goes here

loop = asyncio.get_event_loop()
coro = loop.create_server(EchoServer, '127.0.0.1', 8888)
server = loop.run_until_complete(coro)
print('serving on {}'.format(server.sockets[0].getsockname()))

try:
    loop.run_forever()
except KeyboardInterrupt:
    print("exit")
finally:
    server.close()
    loop.close()

What I'm trying to do is add a client piece where I've commented that will connect to a new server and send the data off that-a-way. There's the echo client, but I need a process that looks like this:

    +-----------+    +-----------+    +--------------+
    | My Server |    | My Client |    | Other Server |
    +-----------+    +-----------+    +--------------+
          |                |                 |
 ===>Get some data         |                 |
          |                |                 |
      Send data ---------->|                 |
          |                |                 |
          |            Send data ----------->|
          |                |                 |
          |                |              Do Stuff
          |                |                 |
          |                | <-----------Send Data
          |                |                 |
          | <--------- Send data             |
          |                |                 |
 <=== Send data            |                 |
          |                |                 |
          |                |                 |
          |                |                 |
          |                |                 |

Obviously I can do this synchronously, but I'm trying to make the client -> other server bit async, and I'm not really figuring out how to use the asyncio methods to communicate between my server piece and a client piece.

What do I need to do here?

Was it helpful?

Solution

Here is a simple proxy which allow you to wget 127.0.0.1:8888 and get a html response from google:

import asyncio

class Client(asyncio.Protocol):

    def connection_made(self, transport):
        self.connected = True
        # save the transport
        self.transport = transport

    def data_received(self, data):
        # forward data to the server
        self.server_transport.write(data)

    def connection_lost(self, *args):
        self.connected = False

class Server(asyncio.Protocol):
    clients = {}
    def connection_made(self, transport):
        # save the transport
        self.transport = transport

    @asyncio.coroutine
    def send_data(self, data):
        # get a client by its peername
        peername = self.transport.get_extra_info('peername')
        client = self.clients.get(peername)
        # create a client if peername is not known or the client disconnect
        if client is None or not client.connected:
            protocol, client = yield from loop.create_connection(
                Client, 'google.com', 80)
            client.server_transport = self.transport
            self.clients[peername] = client
        # forward data to the client
        client.transport.write(data)

    def data_received(self, data):
        # use a task so this is executed async
        asyncio.Task(self.send_data(data))

@asyncio.coroutine
def initialize(loop):
    # use a coroutine to use yield from and get the async result of
    # create_server
    server = yield from loop.create_server(Server, '127.0.0.1', 8888)

loop = asyncio.get_event_loop()

# main task to initialize everything
asyncio.Task(initialize(loop))

# run
loop.run_forever()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top