server.py

import socket
import selectors
import types

host, port = "127.0.0.1", 65432
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)   # register for conn, for later communication


def service_connection(key, mask):
    conn, data = key.fileobj, key.data      # conn socket actually
    
    if mask & selectors.EVENT_READ:
        recv_data = conn.recv(1024)  # Should be ready to read
        if recv_data:
            data.outb += recv_data
        else:
            print("closing connection to", data.addr)
            sel.unregister(conn)
            conn.close()
    if mask & selectors.EVENT_WRITE:
        if data.outb:
            print("echoing", repr(data.outb), "to", data.addr)
            sent = conn.send(data.outb)  # Should be ready to write
            data.outb = data.outb[sent:]


lsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
lsock.bind((host, port))
lsock.listen()
print("listening on", (host, port))
lsock.setblocking(False)

# later listening operation committed to sel
# server was registered without data
sel.register(lsock, selectors.EVENT_READ, data=None)

try:
    while True:
        events = sel.select(timeout=None)   # when read operation is allowed
        for key, mask in events:
            if key.data is None:    # now we know it is server here, ready to accept connection
                accept_wrapper(key.fileobj)
            else:
                service_connection(key, mask)   # conn here, services should be offered
except KeyboardInterrupt:
    print("caught keyboard interrupt, exiting")
finally:
    sel.close()

你可能感兴趣的:(server.py)