Python Network Programming: Building TCP and UDP Socket Applications

Sockets as Application Abstractions

To enable inter-process communication across a network, every active process must possess a unique identifier. Sockets serve as the fundamental mechanism for this exchange. Functionally, a socket operates as an abstraction layer situated between the Application Layer and the Transport Layer of the network stack. By encapsulating the complexities of the TCP/IP suite, sockets expose simplified interfaces that developers utilize to manage data transmission.

There are distinct familise of sockets categorized by their scope:

  • Local Communication: Identified as AF_UNIX, utilized for interactions within the same machine.
  • Network Communication: Identified as AF_INET, designed for IP-based communications over networks.

TCP-Based Socket Implementation

The Transmission Control Protocol (TCP) is connection-oriented. Communication typically initiates when a client requests a connection from a listening server. The following example demonstrates a basic server-client interaction.

Server-Side Logic

import socket

# Establish the socket instance
# Family: IPv4, Type: Stream (TCP)
server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Assign local host and port
host = '127.0.0.1'
port = 8000
server_sock.bind((host, port))

# Begin accepting incoming connections (Queue size: 5)
server_sock.listen(5)
print("Server started, waiting for connections...")

try:
    # Block until a client connects
    conn, addr = server_sock.accept()
    print(f"Connected by {addr}")

    # Receive payload (Bytes limit: 1024)
    data = conn.recv(1024)
    
    # Echo back modified data
    if data:
        response = data.upper()
        conn.sendall(response)
finally:
    conn.close()
    server_sock.close()

Client-Side Logic

import socket

# Create client socket
cli_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

target_host = '127.0.0.1'
target_port = 8000

# Initiate connection
cli_sock.connect((target_host, target_port))

# Transmit UTF-8 encoded string
msg = "hello"
cli_sock.send(msg.encode('utf-8'))

# Capture response
resp = cli_sock.recv(1024)
print(f"Server Reply: {resp.decode('utf-8')}")

cli_sock.close()

Establishing Continuous Communication Loops

Basic single-request models are often insufficient. Real-world applications require persistent sessions allowing multiple exchanges before termination. This requires wrapping the accept and receive/send logic within event loops.

import socket

def run_server():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind(('0.0.0.0', 9090))
    s.listen(10)
    print("Listening on 9090...")

    while True:
        try:
            conn, addr = s.accept()
            print(f"New connection from {addr}")
            
            while True:
                buffer = conn.recv(1024)
                if not buffer:
                    break
                
                msg = buffer.decode().upper()
                print(f"Received: {msg}")
                
                # Send processed response
                conn.send(msg.encode())
        except Exception as e:
            print(f"Error occurred: {e}")
        finally:
            conn.close()

if __name__ == "__main__":
    run_server()

The corresponding client script must also implement a loop to facilitate continuous interaction rather than sending a single packet.

def run_client():
    c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    c.connect(('localhost', 9090))

    while True:
        user_input = input("Enter message > ")
        if not user_input:
            break
        
        c.send(user_input.encode('utf-8'))
        response = c.recv(1024)
        print(f"Response: {response.decode()}")

run_client()

UDP Protocol Implementation

Unlike TCP, the User Datagram Protocol (UDP) is connectionless. It prioritizes speed over reliability. Data is sent via datagrams without establishing a persistent session. In Python, the socket type changes to SOCK_DGRAM.

UDP Server

import socket

u_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
u_server.bind(('127.0.0.1', 7777))

while True:
    # recvfrom returns tuple (data, address)
    data, client_ip = u_server.recvfrom(1024)
    print(f"From {client_ip}: {data}")
    
    # Send response directly to the sender's address
    u_server.sendto(data.upper(), client_ip)

UDP Client

u_cli = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
dest_addr = ('127.0.0.1', 7777)

while True:
    msg = input("Type message > ")
    u_cli.sendto(msg.encode('utf-8'), dest_addr)
    
    res, _ = u_cli.recvfrom(1024)
    print(f"Got: {res}")

u_cli.close()

Tags: python socket-interface tcp-session udp-packet network-stack

Posted on Thu, 11 Jun 2026 18:42:26 +0000 by valerie19