Search code examples
pythontornado

How to read a single keypress from Tornado's IOStream


I have a simple tornado application which reads data from a telnet client. I'm using TCPServer based handler to handle telnet session (code samples simplified).

class CliServer(TCPServer, LoggerMixin):
  def __init__(self):
    super(CliServer, self).__init__()

  def handle_stream(self, stream, address):
    #Some irrelevant code
    self.stream.read_bytes(max_buffsize, callback=self._on_read, streaming_callback=None, partial=True)

  def _on_read(self, data)
    #process data
    pass

The handler is registered in the main IOLoop:

my_fd = self.create_socket(self.options.port, self.options.host)
server = CliServer(self.options.current_scope)
server.add_socket(socket.fromfd(my_fd,
                                socket.AF_INET,
                                socket.SOCK_STREAM))

I want to receive any chunk of data as soon as it has been read from the socket. This chunk of data will be processd by "CliServer._on_read callback".

The problem with my current implementation is that method BaseIOStream.read_bytes provides me with data as soon as it has been terminated with "\r\n", which is too late for me. For example when a telnet user types "ab\tc\n", the _on_read callback is called once with "ab\tc" data, instead of being called 4 times with each character ('a', 'b', '\t', 'c').

What am I doing wrong?


Solution

  • The telnet client is defaulting to line-buffered mode, so it doesn't send anything until the user presses enter. You can use telnet options to change this mode: Send data over telnet without pressing enter