0

I am trying to convert the following echo server IRC alike chat terminal into asyncio , but I don't think too much information about trio since it's new, but what is the translation of this to asyncio?

import trio
from itertools import count
from datetime import datetime

PORT = 9999
BUFSIZE = 16384
CONNECTION_COUNTER = count()

class ServerProtocol:

    def __init__(self, server_stream):
        self.ident = next(CONNECTION_COUNTER)
        self.stream = server_stream

    async def listen(self):
        while True:
            data = await self.stream.receive_some(BUFSIZE)
            print("echo_server {}: received data {!r}".format(self.ident, data))
            if not data:
                print("echo_server {}: connection closed".format(self.ident))
                return
            print("echo_server {}: sending data {!r}".format(self.ident, data))
            await self.stream.send_all('success'.encode())


class Server:

    def __init__(self):
        self.protocols = []

    async def receive_connection(self, server_stream):
        print('{} - {} CONNECTED.'.format(datetime.now(), dir(server_stream)))
        sp: ServerProtocol = ServerProtocol(server_stream)
        self.protocols.append(sp)
        await sp.listen()


async def main():
    await trio.serve_tcp(Server().receive_connection, PORT)

trio.run(main)
etyzz
  • 43
  • 5

2 Answers2

3

Thanks to anyio you don't have to change much of your code to make it work with asyncio ;)

import anyio
from itertools import count
from datetime import datetime

PORT = 9999
BUFSIZE = 16384
CONNECTION_COUNTER = count()


class ServerProtocol:

    def __init__(self, server_stream):
        self.ident = next(CONNECTION_COUNTER)
        self.stream = server_stream

    async def listen(self):
        async with self.stream:
            data = await self.stream.receive(BUFSIZE)
            print("echo_server {}: received data {!r}".format(self.ident, data))
            if not data:
                print("echo_server {}: connection closed".format(self.ident))
                return
            print("echo_server {}: sending data {!r}".format(self.ident, data))
            await self.stream.send('success'.encode())


class Server:

    def __init__(self):
        self.protocols = []

    async def receive_connection(self, server_stream):
        print('{} - {} CONNECTED.'.format(datetime.now(), dir(server_stream)))
        sp: ServerProtocol = ServerProtocol(server_stream)
        self.protocols.append(sp)
        await sp.listen()


async def main():
    listener = await anyio.create_tcp_listener(local_port=PORT)
    await listener.serve(Server().receive_connection)


anyio.run(main)

You should definitely take a look at anyio :)

le_woudar
  • 63
  • 6
0

I'd go with something like:

import asyncio
from itertools import count

PORT = 9999
BUFSIZE = 16384
CONNECTION_COUNTER = count()

class ServerProtocol:
    def __init__(self, read, write):
        self.ident = next(CONNECTION_COUNTER)
        self.read = read
        self.write = write

    async def listen(self):
        while True:
            data = await self.read.read(BUFSIZE)
            print("echo_server {}: received data {!r}".format(self.ident, data))
            if not data:
                print("echo_server {}: connection closed".format(self.ident))
                return
            print("echo_server {}: sending data {!r}".format(self.ident, data))
            self.write.write('success'.encode())
            await self.write.drain()

class Server:
    def __init__(self):
        self.protocols = []

    async def receive_connection(self, read, write):
        sp: ServerProtocol = ServerProtocol(read, write)
        self.protocols.append(sp)
        await sp.listen()

async def main():
    server = await asyncio.start_server(Server().receive_connection, '127.0.0.1', PORT)
    async with server:
        await server.serve_forever()

asyncio.run(main())

Note that I've kept your name ServerProtocol, but keep in mind that the "protocol" classes have a different meaning in asyncio. The code uses the asyncio "streams" layer (much like the trio original) and not the lower-level transport/protocol layer as might be understood from the "protocol" suffix in the name of the class.

user4815162342
  • 104,573
  • 13
  • 179
  • 246