1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
"""Run a TCP server that computes euclidean norm of vectors for its clients.
Run the server:
$ python3.6 norm_server.py
Serving on ('127.0.0.1', 8888)
Test using netcat client:
$ nc localhost 8888
--------------------------------------
Compute the Euclidean norm of a vector
--------------------------------------
[...]
"""
import math
import asyncio
from aiostream import pipe, stream
# Constants
INSTRUCTIONS = """\
--------------------------------------
Compute the Euclidean norm of a vector
--------------------------------------
Enter each coordinate of the vector on a separate line, and add an empty
line at the end to get the result. Anything else will result in an error.
> """
ERROR = """\
-> Error ! Try again...
"""
RESULT = """\
-> Euclidean norm: {}
"""
# Client handler
async def euclidean_norm_handler(
reader: asyncio.StreamReader, writer: asyncio.StreamWriter
) -> None:
# Define lambdas
def strip(x: bytes, *_: object) -> str:
return x.decode().strip()
def nonempty(x: str) -> bool:
return x != ""
def square(x: float, *_: object) -> float:
return x**2
def write_cursor(_: float) -> None:
return writer.write(b"> ")
def square_root(x: float, *_: object) -> float:
return math.sqrt(x)
# Create awaitable
handle_request = (
stream.iterate(reader)
| pipe.print("string: {}")
| pipe.map(strip)
| pipe.takewhile(nonempty)
| pipe.map(float)
| pipe.map(square)
| pipe.print("square: {:.2f}")
| pipe.action(write_cursor)
| pipe.accumulate(initializer=0.0)
| pipe.map(square_root)
| pipe.print("norm -> {:.2f}")
)
# Loop over norm computations
while not reader.at_eof():
writer.write(INSTRUCTIONS.encode())
try:
result = await handle_request
except ValueError:
writer.write(ERROR.encode())
else:
writer.write(RESULT.format(result).encode())
# Main function
async def main(bind: str = "127.0.0.1", port: int = 8888) -> None:
# Start the server
server = await asyncio.start_server(euclidean_norm_handler, bind, port)
# Serve requests until Ctrl+C is pressed
print("Serving on {}".format(server.sockets[0].getsockname()))
async with server:
await server.serve_forever()
# Main execution
if __name__ == "__main__":
asyncio.run(main())
|