aioquic (QUIC implementation with Python): Hello, World
Install Dependencies
Python Virtual Environment and OpenSSL are required to be installed. Following commands are for Ubuntu and Debian-based distributions for any other OS or Linux distribution, please check the concerned documentations.
Create Project Directory
Create and Activate Python Virtual Environment
Create requirements.txt
Create file requirements.txt
with following content:
aioquic==1.2.0
asyncio==4.0.0
attrs==25.3.0
certifi==2025.8.3
cffi==1.17.1
cryptography==45.0.6
pyasn1==0.6.1
pyasn1_modules==0.4.2
pycparser==2.22
pylsqpack==0.3.22
pyOpenSSL==25.1.0
service-identity==24.2.0
typing_extensions==4.14.1
Install Python Dependencies
Generate Self-Signed Certificate for Local Host
openssl req \
-new \
-newkey rsa:2048 \
-days 365 \
-nodes \
-x509 \
-keyout key.pem \
-out cert.pem \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost"
Create Server
Create server file server.py
with following content:
import asyncio
from aioquic.asyncio import QuicConnectionProtocol, serve
from aioquic.quic.configuration import QuicConfiguration
# Define server protocol (how to handle messages)
class ServerProtocol(QuicConnectionProtocol):
def quic_event_received(self, event):
if hasattr(event, "data"): # If data is received
print("Server received:", event.data.decode())
# Echo back to client
self._quic.send_stream_data(event.stream_id, b"Hello from server!")
# Run the QUIC server
async def main():
config = QuicConfiguration(is_client=False)
config.load_cert_chain("cert.pem", "key.pem") # TLS cert required
# Listen on localhost:4433
await serve("localhost", 4433, configuration=config, create_protocol=ServerProtocol)
await asyncio.get_running_loop().create_future() # Keep server running
if __name__ == "__main__":
asyncio.run(main())
Create Client
Create client file client.py
with following content:
import asyncio
from aioquic.asyncio import connect, QuicConnectionProtocol
from aioquic.quic.configuration import QuicConfiguration
from aioquic.quic.events import StreamDataReceived
class ClientProtocol(QuicConnectionProtocol):
def quic_event_received(self, event):
if isinstance(event, StreamDataReceived):
print("Client received:", event.data.decode())
async def main():
config = QuicConfiguration(is_client=True)
config.verify_mode = False # disable TLS verification for local testing
config.load_verify_locations("cert.pem")
# Connect to server
async with connect(
"localhost", 4433, configuration=config, create_protocol=ClientProtocol
) as client:
stream_id = client._quic.get_next_available_stream_id()
client._quic.send_stream_data(stream_id, b"Hello from client!")
# Keep running for a bit to receive server reply
await asyncio.sleep(2)
if __name__ == "__main__":
asyncio.run(main())
Run Server
Run Client
Now open another terminal, go to same directory, activate Python Virtual Environment, and then run following command: