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()
网友评论