Created
April 13, 2023 06:36
-
-
Save KrisMelikova/eb8dbe4bfca91b604375ccabdce971b0 to your computer and use it in GitHub Desktop.
A simple echo server with asyncio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import asyncio | |
from asyncio import AbstractEventLoop | |
import socket | |
import logging | |
import signal | |
from typing import List | |
async def echo(connection: socket, loop: AbstractEventLoop) -> None: | |
try: | |
while data := await loop.sock_recv(connection, 1024): | |
print('got data!') | |
if data == b'boom\r\n': | |
raise Exception("Неожиданная ошибка сети") | |
await loop.sock_sendall(connection, data) | |
except Exception as ex: | |
logging.exception(ex) | |
finally: | |
connection.close() | |
echo_tasks = [] | |
async def connection_listener(server_socket, loop): | |
while True: | |
connection, address = await loop.sock_accept(server_socket) | |
connection.setblocking(False) | |
print(f"Получено сообщение от {address}") | |
echo_task = asyncio.create_task(echo(connection, loop)) | |
echo_tasks.append(echo_task) | |
class GracefulExit(SystemExit): | |
pass | |
def shutdown(): | |
raise GracefulExit() | |
async def close_echo_tasks(echo_tasks: List[asyncio.Task]): | |
waiters = [asyncio.wait_for(task, 2) for task in echo_tasks] | |
for task in waiters: | |
try: | |
await task | |
except asyncio.exceptions.TimeoutError: | |
# Здесь мы ожидаем истечения тайм-аута | |
pass | |
async def main(): | |
server_socket = socket.socket() | |
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
server_address = ('127.0.0.1', 8000) | |
server_socket.setblocking(False) | |
server_socket.bind(server_address) | |
server_socket.listen() | |
for signame in {'SIGINT', 'SIGTERM'}: | |
loop.add_signal_handler(getattr(signal, signame), shutdown) | |
await connection_listener(server_socket, loop) | |
loop = asyncio.new_event_loop() | |
try: | |
loop.run_until_complete(main()) | |
except GracefulExit: | |
loop.run_until_complete(close_echo_tasks(echo_tasks)) | |
finally: | |
loop.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Try it:
telnet localhost 8000