Asyncio problem, looking for advice.

Benjamin Risher brisher777 at gmail.com
Thu Nov 27 09:27:05 EST 2014


Hello all,

I'm working on a project to learn asyncio and network programming.  What I'm trying to do is forward a connection from myself to another machine.  Kind of like an asynchronous python implementation of fpipe.  

In a nutshell:

1 --> start a server listening on localhost
2 --> connect to server 
3 --> server connects to a listening service (ssh for instance)
4 --> server handles both connections to pass traffic back and forth through each

What I have now *kind of* works.  It sends data back and forth, but when I ssh to localhost -p 12345, i never get the password prompt.  It looks like one packet hangs out and doesn't get sent from what I saw in tcpdump.  

Any help would be greatly appreciated.  


Here's a link to the same code as below, just with syntax highlighting etc...
http://pastebin.com/iLE4GZH3


import asyncio
import logging


class MyServer:
    def __init__(self, loop):
        self.server = None
        self.loop = loop
        self.clients = dict()
        self.log = logging.getLogger(__name__)

    def _accept_client(self, client_reader, client_writer):
        """ Client initially drops in here """
        task = asyncio.Task(self._handle_client(client_reader, client_writer))
        self.clients[task] = (client_reader, client_writer)

        def client_done(task):
            self.clients[task][1].close()  # closes the StreamWriter that was part of the task
            del self.clients[task]

        self.log.info("New connection.")
        task.add_done_callback(client_done)

    @asyncio.coroutine
    def _handle_client(self, client_reader, client_writer):
        """ Try to connect to port 22 and broker between 2 connections.

        :param client_reader: StreamReader object
        :param client_writer: StreamWriter object
        """
        reader, writer = yield from asyncio.async(asyncio.open_connection('localhost', 22))

        while True:
            client_data = yield from asyncio.async(self.read_data(client_reader))
            if client_data:
                writer.write(client_data)
                yield from writer.drain()
                
            server_data = yield from asyncio.async(self.read_data(reader))
            if server_data:
                client_writer.write(server_data)
                yield from client_writer.drain()


    @asyncio.coroutine
    def read_data(self, reader):
        data = None

        while True:
            print('top of while')
            data = yield from asyncio.Task(reader.read(2048))
            return data

    def start(self):
        """ start the server listening on 12345 """

        self.server = self.loop.run_until_complete(
            asyncio.streams.start_server(
                self._accept_client,                 # client_connected_callback
                'localhost',                         # host
                12345,                               # port
                loop=self.loop                       # loop
            )
        )

    def stop(self):
        if self.server:
            self.server.close()
            self.loop.run_until_complete(self.server.wait_closed())
            self.server = None

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    my_server = MyServer(loop)
    my_server.start()
    loop.run_forever()
    my_server.stop()



More information about the Python-list mailing list