New chat server example

34 views
Skip to first unread message

Ron Frederick

unread,
Aug 17, 2016, 1:46:02 AM8/17/16
to asyncssh-users, asyncs...@googlegroups.com
Some time ago someone asked about adding an AsyncSSH example which showed managing multiple connections in a single application. Tonight, I added a multi-user chat server example along those lines. It also demonstrates some other recent additions to AsyncSSH such as support for the Python 3.5 async syntax, async iterators for reading lines from SSHStreams, and the new built-in line editor capability when clients of an AsyncSSH server request a pseudo-terminal.

You can find the example at http://asyncssh.readthedocs.io/en/develop/#serving-multiple-clients, or check it out below:

import asyncio, asyncssh, sys

class ChatClient:
    _clients = []

    def __init__(self, stdin, stdout):
        self._stdin = stdin
        self._stdout = stdout

    @classmethod
    async def handle_session(cls, stdin, stdout, stderr):
        await cls(stdin, stdout).run()

    def write(self, msg):
        self._stdout.write(msg)

    def broadcast(self, msg):
        for client in self._clients:
            if client != self:
                client.write(msg)

    async def run(self):
        self.write('Welcome to chat!\n\n')

        self.write('Enter your name: ')
        name = (await self._stdin.readline()).rstrip('\n')

        self.write('\n%d other users are connected.\n\n' % len(self._clients))

        self._clients.append(self)
        self.broadcast('*** %s has entered chat ***\n' % name)

        try:
            async for line in self._stdin:
                self.broadcast('%s: %s' % (name, line))
        except asyncssh.BreakReceived:
            pass

        self.broadcast('*** %s has left chat ***\n' % name)
        self._clients.remove(self)

async def start_server():
    await asyncssh.listen('', 8022, server_host_keys=['ssh_host_key'],
                          authorized_client_keys='ssh_user_ca',
                          session_factory=ChatClient.handle_session)

loop = asyncio.get_event_loop()

try:
    loop.run_until_complete(start_server())
except (OSError, asyncssh.Error) as exc:
    sys.exit('Error starting server: ' + str(exc))

loop.run_forever()

If anyone has questions about this, please let me know.

You may also want to check out the updated client examples at http://asyncssh.readthedocs.io/en/develop/#client-examples which demonstrate the greatly simplified SSHClientProcess APIs.
-- 
Ron Frederick



Reply all
Reply to author
Forward
0 new messages