Blog 11: Python and Networking – Sockets Programming 101

Python and Networking – Sockets Programming 101

Python and Networking – Sockets Programming 101

Sockets are one of the foundational building blocks for network communication. In Python, the socket module allows you to create clients and servers that communicate over TCP or UDP. This tutorial will introduce you to the basics of socket programming, ideal for ethical hackers, cybersecurity professionals, and automation enthusiasts.


What is a Socket?

A socket is a software endpoint that establishes bidirectional communication between a server and one or more clients. In Python, the socket module provides a standard way to work with low-level networking.

1. Socket Overview:

  • Module to create & manage network connections.
  • Low-level interface to BSD sockets.
  • Used for clients, servers, raw packet sniffers, bind shells, etc.

2. Socket Creation Syntax:

socket.socket(family=AF_INET, type=SOCK_STREAM, proto=0)

Common Parameters:

Parameter Meaning
AF_INET IPv4
AF_INET6 IPv6
SOCK_STREAM TCP
SOCK_DGRAM UDP
SOCK_RAW Raw access (needs root)
proto Usually 0 (auto selected)

Basic Socket Functions

  • socket() - Create a new socket
  • bind() - Bind the socket to a specific address and port
  • listen() - Listen for incoming connections (server)
  • accept() - Accept a connection (server)
  • connect() - Connect to a remote socket (client)
  • send() and recv() - Send and receive data

Example 1: Basic TCP Server

import socket

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('0.0.0.0', 9999))
server.listen(5)
print("[*] Listening on port 9999")

client_socket, addr = server.accept()
print(f"[*] Accepted connection from {addr}")

client_socket.send(b"Hello from server!")
client_socket.close()

Explaination:

import socket
  • This brings in the socket module, which lets you do network communication (like connecting to websites or other computers).
  • Think of it as loading the tools needed to talk over the internet.

  • server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  • This creates a socket (like a phone you can use to talk to someone).
  • AF_INET means you're using IPv4 (normal IP addresses like 192.168.1.1).
  • SOCK_STREAM means you're using TCP, which is a reliable connection (like a phone call, where both sides can talk and listen).


  • server.bind(('0.0.0.0', 9999))
  • This binds the server to a port on your computer.
  • '0.0.0.0' means listen on all network interfaces (Wi-Fi, Ethernet, etc.).
  • 9999 is the port number — kind of like the "door number" where your server will wait for connections.


  • server.listen(5)
  • This tells the server to start listening for connections.
  • The 5 means up to 5 connections can wait in line to be accepted.


  • print("[*] Listening on port 9999")
  • Just a message so you (the user) know the server is running and ready on port 9999.


  • client_socket, addr = server.accept()
  • This waits for a client to connect.
  • When someone connects, it returns:
  • client_socket → the connection to the client (like a private line).
  • addr → the client's address (IP and port).


  • print(f"[*] Accepted connection from {addr}")
  • Shows a message with the address of the client that just connected.

  • client_socket.send(b"Hello from server!")
  • This sends a message to the client.
  • The b before the string means it’s being sent as bytes, which is required by sockets.


  • client_socket.close()
  • Closes the connection to that client.


  • Summary:

    This is a very basic TCP server. It:
    1. Starts listening on port 9999.
    2. Waits for one client to connect.
    3. Sends that client a “Hello” message.
    4. Then closes the connection.

    Example 2: Basic TCP Client

    import socket
    
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', 9999))
    
    response = client.recv(4096)
    print(response.decode())

    Explaination:

    import socket
  • This loads the socket module, so you can use it to connect to servers over the internet or local network.

  • client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  • This creates a new socket (like picking up your phone to call someone).
  • AF_INET → you're using IPv4 addresses (like 127.0.0.1).
  • SOCK_STREAM → you're using TCP (a reliable connection, like a phone call).

  • client.connect(('127.0.0.1', 9999))
  • This tells your client to connect to a server.
  • '127.0.0.1' is the localhost, meaning your own computer.
  • 9999 is the port number where the server is listening.
  • So, you're connecting to a server running on your computer, on port 9999.

  • response = client.recv(4096)
  • This waits to receive data from the server.
  • It can receive up to 4096 bytes (that’s just the maximum size in this line).

  • print(response.decode())
  • The data you got is in bytes, so .decode() turns it into a regular string.
  • Then it prints the message you got from the server.
  • Summary (in real-world terms):

    This client:
  • Picks up the phone (creates a socket).
  • Dials your own computer on port 9999.
  • Waits to hear a message (like “Hello from server!”).
  • Prints that message on screen.

  • Example: 3 Basic UDP Server

    import socket
    
    host = "127.0.0.1"  # Listen on localhost
    port = 4444
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.bind((host, port))  # Bind the socket to an address and port
    
    print(f"UDP server listening on {host}:{port}")
    
    while True:
        data, addr = sock.recvfrom(1024)  # Receive data and sender's address
        print(f"Received message: {data.decode()} from {addr}")
        # Optional: Send a response back
        sock.sendto(b"Echo: " + data, addr) 
    

    Explaination:

    First: What’s different here?

  • This code is for a UDP server, not TCP.
  • UDP is like sending postcards — fast, simple, no handshake, but not guaranteed to arrive.
  • TCP is like a phone call — reliable, but needs a connection first.

  • Now, let’s understand the code line by line:

    import socket
  • Loads Python's socket module so you can do network stuff like creating servers.

  • host = "127.0.0.1" # Listen on localhost
  • You're saying: “This server will run on localhost,” which means only your own computer can connect.

  • port = 4444
  • This is the port number your server will listen on.
  • Think of it as a door number on your computer.

  • sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  • You’re creating a UDP socket:
  • AF_INET → IPv4
  • SOCK_DGRAM → UDP (not TCP)
  • Think of this like setting up a mailbox that sends and receives short messages (datagrams).

  • sock.bind((host, port))
  • This attaches (binds) the socket to a specific IP and port, so it can start receiving messages.

  • print(f"UDP server listening on {host}:{port}")
  • Just tells you: “The server is ready and listening for messages.”

  • while True:
  • Starts a loop that runs forever — keeps waiting for new messages.

  • data, addr = sock.recvfrom(1024)
  • Waits for a message to arrive (up to 1024 bytes).
  • When a message comes:
  • data = the message content
  • addr = the sender’s address (IP and port)

  • print(f"Received message: {data.decode()} from {addr}")
  • Prints the message and who sent it.
  • .decode() converts the message from bytes to a readable string.

  • sock.sendto(b"Echo: " + data, addr)
  • Sends a response back to the sender.
  • In this case, it sends back the same message, prefixed with "Echo: ".
  • This makes it an echo server.

  • Summary:

  • This is a simple UDP echo server:
  • Listens on your computer at port 4444.
  • Waits for messages.
  • When it gets one, it prints it out.
  • Then it sends the same message back to the sender.

  • Example: 4 Basic UDP Client

    import socket
    
    host = "127.0.0.1"  # Server IP address
    port = 4444
    MESSAGE = b"Hello, UDP Server!"
    
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.sendto(MESSAGE, (host, port))  # Send data to the server
    
    # Optional: Receive a response from the server
    data, addr = sock.recvfrom(1024)
    print(f"Received response: {data.decode()} from {addr}")
    
    sock.close()
    

    Explaination:

    import socket
  • This loads the socket module so we can use it to send messages over the network.

  • host = "127.0.0.1"
    port = 4444
  • These lines define where the client will send the message:
  • host = "127.0.0.1" → send to your own computer (localhost).
  • port = 4444 → the UDP server's port number.

  • MESSAGE = b"Hello, UDP Server!"
  • This is the message the client will send.
  • The b means it's in byte format, which is required for socket communication.

  • sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  • This creates a UDP socket:
  • AF_INET = use IPv4
  • SOCK_DGRAM = use UDP (not TCP)
  • This socket is like a "virtual envelope" ready to send data.

  • sock.sendto(MESSAGE, (host, port))
  • This sends the MESSAGE to the UDP server at 127.0.0.1:4444.

  • data, addr = sock.recvfrom(1024)
  • After sending the message, the client waits to receive a response from the server.
  • It will accept up to 1024 bytes.
  • data = the message received
  • addr = the address of the server that sent it

  • print(f"Received response: {data.decode()} from {addr}")
  • This prints out the message received from the server.
  • .decode() turns the bytes into a human-readable string.

  • sock.close()
  • Closes the UDP socket — like hanging up or sealing the connection.

  • Summary:

    This UDP client:

  • Writes a message (“Hello, UDP Server!”).
  • Sends it to the UDP server on your own computer at port 4444.
  • Waits for a reply.
  • Prints the reply.
  • Closes the socket when done.

  • Common Use Cases:

    • Port scanners
    • Backdoors and reverse shells
    • Custom servers and clients for penetration testing
    • Network sniffing (in combination with other tools)

    Socket Modes:

    • TCP (SOCK_STREAM): Reliable, connection-based communication
    • UDP (SOCK_DGRAM): Fast, connectionless communication

    Conclusion:

    With just a few lines of Python, you can create powerful networking tools. This is just the beginning — you can build full network scanners, web clients, or even chat apps using the socket module. Practice by modifying and expanding these examples!

    Comments