Asyncio problem, looking for advice.

Akira Li 4kir4.1i at
Fri Nov 28 13:10:35 CET 2014

Benjamin Risher <brisher777 at> writes:

> 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.

Do you want to emulate `ssh -L 12345:localhost:22 <host>`?

> Here's a link to the same code as below, just with syntax highlighting etc...

There are several issue e.g., unnecessary async(), deprecated Task()
calls but the main issue is that _handle_client() doesn't read
concurrently from the server while client writes to it.

You could use asyncio.wait() to run several tasks in parallel
[1]. Here's a example [2]:

  #!/usr/bin/env python3
  """Forward a local tcp port to host:port.
  Usage: %(prog)s local_port:host:port
    $ python3 # start server
  and in another window:
    $ curl localhost:26992 # connect to it
  import asyncio
  import logging
  import sys
  info = logging.getLogger('forward-port').info
  def copy_stream(reader, writer, bufsize=1<<16):
      while True:
          data = yield from
          if not data:
          yield from writer.drain()
  def port_forwarder(host, port, *, loop):
      def forward(local_reader, local_writer):
          client = local_writer.get_extra_info('peername')
          info('connected client %s %s', *client)
          remote_reader, remote_writer = yield from asyncio.open_connection(host, port, loop=loop)
          yield from asyncio.wait([copy_stream(local_reader, remote_writer),
                                   copy_stream(remote_reader, local_writer)],
          info('disconnected client %s %s', *client)
      return forward
  # main
                      format="%(asctime)-15s %(message)s", datefmt="%F %T")
  if len(sys.argv) != 2:
  local_port, host, port = sys.argv[1].split(':') # e.g., 12345:localhost:22
  loop = asyncio.get_event_loop()
  server = loop.run_until_complete(asyncio.start_server(port_forwarder(host, int(port), loop=loop),
                                                        'localhost', int(local_port), loop=loop))
  info('listening on: %s %s', *server.sockets[0].getsockname())
  for closing in range(2):
      except KeyboardInterrupt:
          if not closing:
              info('closing server')




More information about the Python-list mailing list