Skip to content

Instantly share code, notes, and snippets.

@natej
Created September 10, 2018 23:49

Revisions

  1. natej created this gist Sep 10, 2018.
    71 changes: 71 additions & 0 deletions multiconn-server-exchandler.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,71 @@
    #!/usr/bin/env python3

    import sys
    import socket
    import selectors
    import types

    sel = selectors.DefaultSelector()


    def accept_wrapper(sock):
    conn, addr = sock.accept() # Should be ready to read
    print('accepted connection from', addr)
    conn.setblocking(False)
    data = types.SimpleNamespace(addr=addr, inb=b'', outb=b'')
    events = selectors.EVENT_READ | selectors.EVENT_WRITE
    sel.register(conn, events, data=data)


    def service_connection(key, mask):
    sock = key.fileobj
    data = key.data
    if mask & selectors.EVENT_READ:
    try:
    recv_data = sock.recv(1024) # Should be ready to read
    except BlockingIOError:
    # Resource temporarily unavailable (errno EWOULDBLOCK)
    pass
    else:
    if recv_data:
    data.outb += recv_data
    else:
    print('closing connection to', data.addr)
    sel.unregister(sock)
    sock.close()
    if mask & selectors.EVENT_WRITE:
    if data.outb:
    print('echoing', repr(data.outb), 'to', data.addr)
    try:
    sent = sock.send(data.outb) # Should be ready to write
    except BlockingIOError:
    # Resource temporarily unavailable (errno EWOULDBLOCK)
    pass
    else:
    data.outb = data.outb[sent:]


    if len(sys.argv) != 3:
    print('usage:', sys.argv[0], '<host> <port>')
    sys.exit(1)

    host, port = sys.argv[1], int(sys.argv[2])
    lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    lsock.bind((host, port))
    lsock.listen()
    print('listening on', (host, port))
    lsock.setblocking(False)
    sel.register(lsock, selectors.EVENT_READ, data=None)

    try:
    while True:
    events = sel.select(timeout=None)
    for key, mask in events:
    if key.data is None:
    accept_wrapper(key.fileobj)
    else:
    service_connection(key, mask)
    except KeyboardInterrupt:
    print('caught keyboard interrupt, exiting')
    finally:
    sel.close()