Skip to content

Instantly share code, notes, and snippets.

@bsidhom
Created October 4, 2022 02:21
Show Gist options
  • Save bsidhom/f9abb5a9eff373b06998459a51c612cd to your computer and use it in GitHub Desktop.
Save bsidhom/f9abb5a9eff373b06998459a51c612cd to your computer and use it in GitHub Desktop.
Simple Python asyncio server and client with a JSON protocol
#!/usr/bin/env python3
import asyncio
import json
import sys
async def main():
reader, writer = await asyncio.open_connection("127.0.0.1", 8888)
messages = ["One", 2, {"thr": "ee"}, ["4"], [5, 6]]
for message in messages:
print(f"sending: {message}")
payload = json.dumps(message).encode()
size = len(payload)
writer.write(size.to_bytes(4, byteorder="big"))
writer.write(payload)
_, response = await asyncio.gather(writer.drain(), reader.read(4))
if len(response) != 4:
raise Exception(
f"incomplete response; expected 4 bytes, got {len(response)}")
response_size = int.from_bytes(response, byteorder="big")
response = await reader.read(response_size)
j = json.loads(response)
print(f"response: {j}")
if __name__ == "__main__":
sys.exit(asyncio.run(main()))
#!/usr/bin/env python3
import asyncio
import json
import sys
async def main():
server = await asyncio.start_server(handle_outer_connection, "127.0.0.1",
8888)
addrs = [s.getsockname() for s in server.sockets]
print(f"listening on {addrs}")
async with server:
await server.serve_forever()
return 0
async def handle_outer_connection(reader, writer):
print("got connection")
try:
await handle_connection(reader, writer)
except Exception as e:
print(f"caught exception: {e}")
finally:
print("closing connection")
writer.close()
await writer.wait_closed()
async def handle_connection(reader, writer):
while True:
req_size = await reader.read(4)
if len(req_size) == 0 and reader.at_eof():
return
elif len(req_size) != 4:
raise Exception(f"incomplete request size: {len(req_size)}")
req_size = int.from_bytes(req_size, byteorder="big")
request = await reader.read(req_size)
request_j = json.loads(request)
response = {"response": request_j}
response_j = json.dumps(response).encode()
response_size = len(response_j)
writer.write(response_size.to_bytes(4, byteorder="big"))
writer.write(response_j)
await writer.drain()
if __name__ == "__main__":
sys.exit(asyncio.run(main()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment