Skip to content

Instantly share code, notes, and snippets.

@marceloalcocer
Last active April 20, 2021 21:17
Show Gist options
  • Save marceloalcocer/15c4bc91ab69f8df465a7eb4acb0db8b to your computer and use it in GitHub Desktop.
Save marceloalcocer/15c4bc91ab69f8df465a7eb4acb0db8b to your computer and use it in GitHub Desktop.
TCP echo server implemented using asyncio
#!/usr/bin/env python3
"""TCP echo server
Implemented using asyncio for concurrent client handling
"""
import asyncio
import argparse
import logging
class EchoServer:
address = "localhost"
port = 8888
_server = None
def __init__(self, address=None, port=None):
logging.basicConfig(
level=logging.INFO,
format="[%(asctime)s] %(levelname)s: %(message)s"
)
if address is not None:
self.address = address
if port is not None:
self.port = port
async def _init_server(self):
"""Instantiate server"""
self._server = await asyncio.start_server(
self._echo,
host=self.address,
port=self.port,
start_serving=False
)
async def _echo(self, reader, writer):
"""Echo connection data"""
client = writer.get_extra_info("peername")
logging.info(f"{client}: Connected")
data = await reader.readline()
while data:
logging.info(f"{client}: Received: {data}")
await asyncio.sleep(1) # Simulate e.g. network latency
writer.write(data)
await writer.drain()
logging.info(f"{client}: Sent: {data}")
data = await reader.readline()
writer.write_eof()
writer.close()
await writer.wait_closed()
logging.info(f"{client}: Disconnected")
async def _listen(self):
"""Start listening"""
async with self._server:
logging.info("Echo server started")
logging.info(f"Listening on {self.address}:{self.port}")
await self._server.serve_forever()
async def __call__(self):
"""Async main"""
await self._init_server()
await self._listen()
def up(self):
"""Start server"""
try:
asyncio.run(self())
except KeyboardInterrupt:
logging.info("Stopping echo server")
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="A simple TCP echo server"
)
parser.add_argument(
"-a", "--address",
nargs="?",
default=EchoServer.address,
help="Server address"
)
parser.add_argument(
"-p", "--port",
nargs="?",
type=int,
default=EchoServer.port,
help="Port to listen on"
)
args = parser.parse_args()
EchoServer(address=args.address, port=args.port).up()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment