Foundations of Python Network Programming

(WallPaper) #1
Chapter 7 ■ Server arChiteCture

129

The asyncio framework supports two programming styles. One, which reminds programmers of the old Twisted
framework under Python 2, lets the user keep up with each open client connection by means of an object instance. In
this design pattern, the steps that Listing 7-6 took to advance a client conversation become method calls on the object
instance. You can see the familiar steps of reading in a question and reeling off a response in Listing 7-7, written in a
way that plugs directly into the asyncio framework.


Listing 7-7. An asyncio Server in the Callback Style


#!/usr/bin/env python3


Foundations of Python Network Programming, Third Edition


https://github.com/brandon-rhodes/fopnp/blob/m/py3/chapter07/srv_asyncio1.py


Asynchronous I/O inside "asyncio" callback methods.


import asyncio, zen_utils


class ZenServer(asyncio.Protocol):


def connection_made(self, transport):
self.transport = transport
self.address = transport.get_extra_info('peername')
self.data = b''
print('Accepted connection from {}'.format(self.address))


def data_received(self, data):
self.data += data
if self.data.endswith(b'?'):
answer = zen_utils.get_answer(self.data)
self.transport.write(answer)
self.data = b''


def connection_lost(self, exc):
if exc:
print('Client {} error: {}'.format(self.address, exc))
elif self.data:
print('Client {} sent {} but then closed'
.format(self.address, self.data))
else:
print('Client {} closed socket'.format(self.address))


if name == 'main':
address = zen_utils.parse_command_line('asyncio server using callbacks')
loop = asyncio.get_event_loop()
coro = loop.create_server(ZenServer, *address)
server = loop.run_until_complete(coro)
print('Listening at {}'.format(address))
try:
loop.run_forever()
finally:
server.close()
loop.close()

Free download pdf