1.7 KiB
1.7 KiB
Exercise 8.5 - Solution
(b) Generators as Tasks Serving Network Connections
Here’s the complete code.
# server.py
from socket import *
from select import select
from collections import deque
= deque()
tasks = {} # sock -> task
recv_wait = {} # sock -> task
send_wait
def run():
while any([tasks, recv_wait, send_wait]):
while not tasks:
= select(recv_wait, send_wait, [])
can_recv, can_send, _ for s in can_recv:
tasks.append(recv_wait.pop(s))for s in can_send:
tasks.append(send_wait.pop(s))= tasks.popleft()
task try:
= task.send(None)
reason, resource if reason == 'recv':
= task
recv_wait[resource] elif reason == 'send':
= task
send_wait[resource] else:
raise RuntimeError('Unknown reason %r' % reason)
except StopIteration:
print('Task done')
def tcp_server(address, handler):
= socket(AF_INET, SOCK_STREAM)
sock 1)
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR,
sock.bind(address)5)
sock.listen(while True:
yield 'recv', sock
= sock.accept()
client, addr
tasks.append(handler(client, addr))
def echo_handler(client, address):
print('Connection from', address)
while True:
yield 'recv', client
= client.recv(1000)
data if not data:
break
yield 'send', client
b'GOT:' + data)
client.send(print('Connection closed')
if __name__ == '__main__':
'',25000), echo_handler))
tasks.append(tcp_server(( run()