Hi,
I have posted the same question to python-tutor list *, but I'm trying
my luck here as advised.

I'm trying to get more familiar with asyncio library. Using python
3.4, I wrote simple echo server (see attachement for the code). I know
that instead of using bare bone send/recv I could use some of the
helper functions, but I want to start with the basics.

Using attached code, I can connect from multiple sources, but echo
won't work for all clients. Also, please look at the `sendall` mehtod
- I have to manually remove write callback, otherwise it will be
called all the time. Any tips on solving this problem?

* https://mail.python.org/pipermail/tutor/2014-March/100679.html
import asyncio
import socket
import time


loop = asyncio.get_event_loop()


class Client:
    def __init__(self, conn):
        self.conn = conn
        self.conn.setblocking(False)

    def recv(self, size):
        "wrap `recv` method with future"
        future = asyncio.Future()

        def _recv():
            try:
                future.set_result(self.conn.recv(size))
            except Exception as exc:
                future.set_exception(exc)

        loop.add_reader(self.conn, _recv)
        return future

    def sendall(self, data):
        "wrap `sendall` method with future"
        future = asyncio.Future()

        def _sendall():
            try:
                # XXX manually remove, because otherwise it will be called
                # forever
                loop.remove_writer(self.conn)
                future.set_result(self.conn.sendall(data))
            except Exception as exc:
                future.set_exception(exc)

        loop.add_writer(self.conn, _sendall)
        return future

    def close(self):
        self.conn.close()


def accept(sock):
    future = asyncio.Future()

    def _accept_client():
        conn, addr = sock.accept()
        future.set_result((Client(conn), addr))

    loop.add_reader(sock, _accept_client)
    return future


def handle_client(conn, addr):
    print("Client connected: {}".format(addr))
    while True:
        data = yield from conn.recv(1024)
        if data.strip() == b'quit':
            conn.close()
            print("Client disconnected: {}".format(addr))
            return
        yield from conn.sendall(data)


@asyncio.coroutine
def test():
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    sock.setblocking(False)
    sock.bind(('localhost', 12345))
    sock.listen(1)
    while True:
        conn, addr = yield from accept(sock)
        asyncio.Task(handle_client(conn, addr))


def main():
    loop.run_until_complete(test())
    loop.close()

if __name__ == "__main__":
    main()
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to