Subprocess Execution, TCP Packet Sticking, Large File Uploads, UDP, and Socketserver

The subprocess module enables the execution of system termianl commands from within Python code and captures their output.

import subprocess

command = input('Enter a terminal command:')

process = subprocess.Popen(
    command,
    shell=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE
)

output = process.stdout.read() + process.stderr.read()
print(output.decode('gbk'))

Network Commend Execution Example

Server

import subprocess
import socket

sock = socket.socket()
sock.bind(('127.0.0.1', 8080))
sock.listen()
conn, addr = sock.accept()

while True:
    command = conn.recv(1024).decode('utf-8')
    
    proc = subprocess.Popen(
        command,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    result = proc.stdout.read() + proc.stderr.read()
    conn.send(result)

Client

import socket

client_socket = socket.socket()
client_socket.connect(('127.0.0.1', 8080))

while True:
    cmd = input('Input command:')
    client_socket.send(cmd.encode('utf-8'))
    response = client_socket.recv(1024).decode('gbk')
    print(response)

TCP Packet Sticking (TCP Nagle Algorithm)

In TCP's streaming protocol, multiple small data packets sent in rapid succession may be combined into a single transmission, causing the receiver to recieve concatenated data.

Server

import socket

serv = socket.socket()
serv.bind(('127.0.0.1', 9090))
serv.listen()
connection, client_addr = serv.accept()

packet1 = connection.recv(1024).decode('utf-8')
packet2 = connection.recv(1024).decode('utf-8')
packet3 = connection.recv(1024).decode('utf-8')
print(f'Packet1:{packet1}, Packet2:{packet2}, Packet3:{packet3}')

Client

import socket
import time

cl = socket.socket()
cl.connect(('127.0.0.1', 9090))

cl.send(b'msg1')
time.sleep(0.5)
cl.send(b'msg2')
time.sleep(0.5)
cl.send(b'msg3')

Using struct for Header-Based Packet Separation

import struct

sample_data = 'example payload'
# Pack an integer into 4 bytes
header = struct.pack('i', 1500)
print(header, len(header))

# Unpack to retrieve the integer
original_length = struct.unpack('i', header)[0]
print(original_length)

Server with struct header

import subprocess
import socket
import struct

server_sock = socket.socket()
server_sock.bind(('127.0.0.1', 7070))
server_sock.listen()
conn, addr = server_sock.accept()

while True:
    cmd = conn.recv(1024).decode('utf-8')
    
    proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    cmd_result = proc.stdout.read() + proc.stderr.read()
    
    result_header = struct.pack('i', len(cmd_result))
    conn.send(result_header)
    conn.send(cmd_result)

Client with struct header

import socket
import struct

cl_sock = socket.socket()
cl_sock.connect(('127.0.0.1', 7070))

while True:
    user_cmd = input('Command:')
    cl_sock.send(user_cmd.encode('utf-8'))
    
    received_header = cl_sock.recv(4)
    data_size = struct.unpack('i', received_header)[0]
    
    actual_data = cl_sock.recv(data_size)
    print(actual_data.decode('gbk'))

Enhanced Header with JSON Metadata

Server

import json
import socket
import struct

s = socket.socket()
s.bind(('127.0.0.1', 6060))
s.listen()
conn, addr = s.accept()

header_bytes = conn.recv(4)
meta_length = struct.unpack('i', header_bytes)[0]
json_bytes = conn.recv(meta_length)
metadata = json.loads(json_bytes.decode('utf-8'))
print(metadata)

Client

import json
import socket
import struct

c = socket.socket()
c.connect(('127.0.0.1', 6060))

file_info = {
    'filename': 'sample_video.mp4',
    'filesize': 50000000
}
json_str = json.dumps(file_info)
json_data = json_str.encode('utf-8')

header = struct.pack('i', len(json_data))
c.send(header)
c.send(json_data)

Large File Upload over TCP

Server

import socket
import struct
import json

serv = socket.socket()
serv.bind(('127.0.0.1', 5050))
serv.listen()

while True:
    conn, addr = serv.accept()
    try:
        while True:
            header = conn.recv(4)
            dict_len = struct.unpack('i', header)[0]
            json_dict = conn.recv(dict_len).decode('utf-8')
            info = json.loads(json_dict)
            
            fname = info.get('filename')
            fsize = info.get('filesize')
            
            with open(fname, 'wb') as f:
                remaining = fsize
                while remaining > 0:
                    chunk = conn.recv(min(1024, remaining))
                    f.write(chunk)
                    remaining -= len(chunk)
            print(f'File {fname} received.')
    except Exception as err:
        print(f'Error: {err}')

Client

import socket
import struct
import json
import os

client = socket.socket()
client.connect(('127.0.0.1', 5050))

filepath = '/path/to/large_file.dat'

while True:
    input('Press Enter to upload:')
    
    with open(filepath, 'rb') as f:
        file_content = f.read()
    
    metadata = {
        'filename': os.path.basename(filepath),
        'filesize': len(file_content)
    }
    
    json_metadata = json.dumps(metadata)
    meta_bytes = json_metadata.encode('utf-8')
    meta_header = struct.pack('i', len(meta_bytes))
    
    client.send(meta_header)
    client.send(meta_bytes)
    
    with open(filepath, 'rb') as f:
        while chunk := f.read(1024):
            client.send(chunk)
    print(f'Uploaded {metadata["filename"]}')

UDP Protocol Basics

UDP is a connectionless datagram protocol without built-in reliability or ordering guarantees.

Server

import socket

udp_server = socket.socket(type=socket.SOCK_DGRAM)
udp_server.bind(('127.0.0.1', 9999))

msg1, addr1 = udp_server.recvfrom(1024)
msg2, addr2 = udp_server.recvfrom(1024)
msg3, addr3 = udp_server.recvfrom(1024)
print(f'{addr1}: {msg1}, {addr2}: {msg2}, {addr3}: {msg3}')

Client

import socket

udp_client = socket.socket(type=socket.SOCK_DGRAM)
server_addr = ('127.0.0.1', 9999)

udp_client.sendto(b'packet1', server_addr)
udp_client.sendto(b'packet2', server_addr)
udp_client.sendto(b'packet3', server_addr)

Simple UDP Chat Room

Server

import socket

server = socket.socket(type=socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 8888))

client_addresses = []

while True:
    data, addr = server.recvfrom(1024)
    if addr not in client_addresses:
        client_addresses.append(addr)
    
    print(f'{addr}: {data.decode()}')
    
    reply = input('Reply to all: ')
    for client in client_addresses:
        server.sendto(reply.encode(), client)
    
    if reply.lower() == 'quit':
        break

Client

import socket
import threading

client = socket.socket(type=socket.SOCK_DGRAM)
server_address = ('127.0.0.1', 8888)

# Receive messages in a separate thread
def receive_messages():
    while True:
        data, _ = client.recvfrom(1024)
        print(f'Server: {data.decode()}')

receiver = threading.Thread(target=receive_messages, daemon=True)
receiver.start()

while True:
    message = input('Your message: ')
    client.sendto(message.encode(), server_address)

Socketserver Module for Simplified Servers

The socketserver module provides higher-level abstractions for creating network servers.

TCPServer Example

import socketserver

class CustomTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        print(f'Connected: {self.client_address}')
        try:
            while True:
                received = self.request.recv(1024).decode('utf-8')
                if not received:
                    break
                response = received.upper()
                self.request.send(response.encode('utf-8'))
        except ConnectionError as e:
            print(f'Connection lost: {e}')

if __name__ == '__main__':
    with socketserver.ThreadingTCPServer(('127.0.0.1', 8080), CustomTCPHandler) as server:
        server.serve_forever()

UDPServer Example

import socketserver

class CustomUDPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        data, socket = self.request
        print(f'Received from {self.client_address}: {data.decode()}')
        socket.sendto(data.upper(), self.client_address)

if __name__ == '__main__':
    with socketserver.ThreadingUDPServer(('127.0.0.1', 9999), CustomUDPHandler) as server:
        server.serve_forever()

Tags: python Network Programming subprocess tcp udp

Posted on Wed, 26 Aug 2026 16:23:17 +0000 by gasxtreme