@@ -473,6 +473,7 @@ having to write a short coroutine to handle the exception and stop the
473473running loop. At :meth: `~BaseEventLoop.run_until_complete ` exit, the loop is
474474no longer running, so there is no need to stop the loop in case of an error.
475475
476+
476477TCP echo server
477478---------------
478479
@@ -483,34 +484,122 @@ TCP echo server example, send back received data and close the connection::
483484 class EchoServer(asyncio.Protocol):
484485 def connection_made(self, transport):
485486 peername = transport.get_extra_info('peername')
486- print('connection from {}'.format(peername))
487+ print('Connection from {}'.format(peername))
487488 self.transport = transport
488489
489490 def data_received(self, data):
490- print('data received: {}'.format(data.decode()))
491+ message = data.decode()
492+ print('Data received: {!r}'.format(message))
493+
494+ print('Send: {!r}'.format(message))
491495 self.transport.write(data)
492496
493- # close the socket
497+ print('Close the socket')
494498 self.transport.close()
495499
496500 loop = asyncio.get_event_loop()
497501 coro = loop.create_server(EchoServer, '127.0.0.1', 8888)
498502 server = loop.run_until_complete(coro)
499- print('serving on {}'.format(server.sockets[0].getsockname()))
500503
504+ # Server requests until CTRL+c is pressed
505+ print('Serving on {}'.format(server.sockets[0].getsockname()))
501506 try:
502507 loop.run_forever()
503508 except KeyboardInterrupt:
504509 print("exit")
505- finally:
506- server.close()
507- loop.close()
510+
511+ # Close the server
512+ server.close()
513+ loop.run_until_complete(server.wait_closed())
514+ loop.close()
508515
509516:meth: `Transport.close ` can be called immediately after
510517:meth: `WriteTransport.write ` even if data are not sent yet on the socket: both
511518methods are asynchronous. ``yield from `` is not needed because these transport
512519methods are not coroutines.
513520
521+
522+ .. _asyncio-udp-echo-client-protocol :
523+
524+ UDP echo client protocol
525+ ------------------------
526+
527+ UDP echo client using the :meth: `BaseEventLoop.create_datagram_endpoint `
528+ method, send data and close the transport when we received the answer::
529+
530+ import asyncio
531+
532+ class EchoClientProtocol:
533+ def __init__(self, message, loop):
534+ self.message = message
535+ self.loop = loop
536+ self.transport = None
537+
538+ def connection_made(self, transport):
539+ self.transport = transport
540+ print('Send:', self.message)
541+ self.transport.sendto(self.message.encode())
542+
543+ def datagram_received(self, data, addr):
544+ print("Received:", data.decode())
545+
546+ print("Close the socket")
547+ self.transport.close()
548+
549+ def error_received(self, exc):
550+ print('Error received:', exc)
551+
552+ def connection_lost(self, exc):
553+ print("Socket closed, stop the event loop")
554+ loop = asyncio.get_event_loop()
555+ loop.stop()
556+
557+ loop = asyncio.get_event_loop()
558+ message = "Hello World!"
559+ connect = loop.create_datagram_endpoint(
560+ lambda: EchoClientProtocol(message, loop),
561+ remote_addr=('127.0.0.1', 9999))
562+ transport, protocol = loop.run_until_complete(connect)
563+ loop.run_forever()
564+ transport.close()
565+ loop.close()
566+
567+
568+ .. _asyncio-udp-echo-server-protocol :
569+
570+ UDP echo server protocol
571+ ------------------------
572+
573+ UDP echo server using the :meth: `BaseEventLoop.create_datagram_endpoint `
574+ method, send back received data::
575+
576+ import asyncio
577+
578+ class EchoServerClientProtocol:
579+ def connection_made(self, transport):
580+ self.transport = transport
581+
582+ def datagram_received(self, data, addr):
583+ message = data.decode()
584+ print('Received %r from %s' % (message, addr))
585+ print('Send %r to %s' % (message, addr))
586+ self.transport.sendto(data, addr)
587+
588+ loop = asyncio.get_event_loop()
589+ print("Starting UDP server")
590+ listen = loop.create_datagram_endpoint(
591+ EchoServerClientProtocol, local_addr=('127.0.0.1', 9999))
592+ transport, protocol = loop.run_until_complete(listen)
593+
594+ try:
595+ loop.run_forever()
596+ except KeyboardInterrupt:
597+ pass
598+
599+ transport.close()
600+ loop.close()
601+
602+
514603.. _asyncio-register-socket :
515604
516605Register an open socket to wait for data using a protocol
0 commit comments