Skip to main content

Simplified Async TCP and UDP Sockets for Python 3.8+

Project description

aio-sockets

💡 Overview

aio-sockets is a lightweight and user-friendly library that provides a simplified, higher-level API for handling asynchronous TCP and UDP network communication in Python. Built on top of the powerful asyncio library, this wrapper abstracts away common complexities, allowing developers to focus on their application logic rather than low-level socket management.

This library is perfect for building high-performance, concurrent network applications like servers, clients, and P2P tools with minimal boilerplate code.

✨ Features

Simplified API: Easy-to-use classes like TCPSocket and UDPSocket encapsulate common operations like sending, receiving, and closing connections.

Context Manager Support: Use async with for both TCP and UDP sockets to ensure resources are automatically and correctly closed, preventing leaks.

Read-with-Timeout: Built-in recv_timeout and recvfrom_timeout methods make it simple to handle non-blocking reads with a defined timeout, preventing your application from hanging.

📦 Installation

This is a single-file library.
1, Simply copy the aio_sockets.py file into your project directory.
2, Or run pip install aio-sockets.

Minimum supported version: Python 3.8

Usage

Basic TCP Server Example

import socket
import aio_sockets as aio
log = print

async def tcp_client(sock: aio.TCPSocket):
    raddr: aio.IPAddress = sock.getpeername()
    log(f'new client {raddr} connected')
    async with sock:
        while True:
            data = await sock.recv()
            if not data:
                log(f'remote {raddr} close connection')
                break
            log(f'recv: {data} from {raddr}')
            log(f'send: {data} to {raddr}')
            await sock.send(data)

async def tcp_server(host: str, port: int, family:socket.AddressFamily = socket.AF_INET):
    async with await aio.start_tcp_server(tcp_client, host, port, family=family) as server:
        sock: aio.trsock.TransportSocket = server.sockets[0]
        log(f'serving on {sock.getsockname()} {family!r}')
        await server.serve_forever()

aio.run(tcp_server('0.0.0.0', 25000)) # aio.run is just asyncio.run

Basic TCP Client Example

import socket
import aio_sockets as aio
log = print

async def tcp_client(server_ip: str, server_port: int, timeout: int = 5,
                     family:socket.AddressFamily = socket.AF_INET):
    log(f'connect to {server_ip}:{server_port}')
    sock: aio.TCPSocket = await aio.open_tcp_connection(server_ip, server_port, family=family)
    laddr, raddr = sock.getsockname(), sock.getpeername()
    log(f'connected, local address={laddr}')
    async with sock:
        for i in range(3):
            data = f'Hi {i}'.encode()
            log(f'{laddr} send to {raddr}: {data}')
            await sock.send(data)
            # data = await sock.recv()
            try:
                data = await sock.recv_timeout(n=8192, timeout=timeout)
                log(f'{laddr} recv: {data}')
                if not data:
                    log(f'server closed connection {laddr}')
                    break
            except TimeoutError as ex:
                log(f'{laddr} recv timeout, ex={ex!r}')

aio.run(tcp_client('127.0.0.1', 25000))

Basic UDP Server Example

import socket
import aio_sockets as aio
log = print

async def udp_server(host: str, port: int, family:socket.AddressFamily = socket.AF_INET):
    sock: aio.UDPSocket = await aio.create_udp_socket(local_addr=(host, port), family=family)
    log(f'serving on {sock.getsockname()} {family!r}')
    async with sock:
        while True:
            data, raddr = await sock.recvfrom()
            log(f'recv from {raddr}: {data}')
            log(f'send to {raddr}: {data}')
            sock.sendto(data, raddr)

aio.run(udp_server('0.0.0.0', 25000))

Basic UDP Client Example

import socket
import aio_sockets as aio
log = print

async def udp_client(server_ip: str, server_port: int, family:socket.AddressFamily = socket.AF_INET):
    sock: aio.UDPSocket
    async with await aio.create_udp_socket(remote_addr=(server_ip, server_port), family=family) as sock:
        laddr, raddr = sock.getsockname(), sock.getpeername()

        async def udp_recv_loop():
            while True:
                data, raddr = await sock.recvfrom()
                log(f'{laddr} recv from {raddr}: {data}')
                if not data:
                    break

        aio.create_task(udp_recv_loop())

        for i in range(3):
            data = f'Hi {i}'.encode()
            log(f'{laddr} send to {raddr}: {data}')
            sock.sendto(data, None)

        await aio.sleep(1) # wait and make udp_recv_loop have time to receive

async def start_udp_client():
    await udp_client('127.0.0.1', 25000)
    await aio.wait_all_tasks_done() # wait for udp_recv_loop to finish

aio.run(start_udp_client())

Running the Examples

To test the examples above, you can use the provided echo_server.py and echo_client.py files.

# Start the echo server, supports both TCP and UDP
python echo_server.py -p 25000                  # supports IPv4 and IPv6
python echo_server.py --host :: -p 25000        # only IPv6
python echo_server.py --host 0.0.0.0 -p 25000   # only IPv4

# Run IPv4 TCP client
python echo_client.py -s 127.0.0.1 -p 25000

# Run IPv4 UDP client
python echo_client.py -s 127.0.0.1 -p 25000 -u

# Run IPv6 TCP client
python echo_client.py -s ::1 -p 25000

# Run IPv6 UDP client
python echo_client.py -s ::1 -p 25000 -u

Echo Server Snapshot:

echo server

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aio_sockets-0.1.1.tar.gz (10.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

aio_sockets-0.1.1-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

File details

Details for the file aio_sockets-0.1.1.tar.gz.

File metadata

  • Download URL: aio_sockets-0.1.1.tar.gz
  • Upload date:
  • Size: 10.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for aio_sockets-0.1.1.tar.gz
Algorithm Hash digest
SHA256 a18be93a84a507d72869662394ebaf3d6a9fff417b46ac98e9a4a73caa57b98f
MD5 15d5696e72a99bca68bb6c13b51cc8a0
BLAKE2b-256 a16c9a6535241eb8f3d8b3720bfd8080eccc9969f8e46b7f6524ae70fbb9d57e

See more details on using hashes here.

File details

Details for the file aio_sockets-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: aio_sockets-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 10.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for aio_sockets-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1879a949ab3e33e97d2b011cef32041cf9a3b28c0d2682745c987465b2180514
MD5 92c04451ec1c2a81419096b2b177dce5
BLAKE2b-256 21c8c77c9b76a082c5a524572ceff0a9436414bafaa78acb2035230fb0b0ddfb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page