Socket Programming

Published May 22, 2025

Socket programming is a fundamental concept in computer networking that enables real-time, bidirectional communication between devices over a network. Whether you’re building a chat app, a multiplayer game, or a live data streaming service, understanding sockets is key. In this quick guide, we’ll break down the essentials of socket programming in a way that’s easy to grasp, even if you’re just starting out. Let’s dive in!

What Are Sockets?

At its core, a socket is an endpoint for sending and receiving data across a network. Think of it as a virtual “plug” or handle that allows two devices to communicate, whether they’re on the same machine or halfway across the world. A handle is an opaque integer used to refer to things that cross an API boundary, in the same way that a Twitter handle refers to a Twitter user. On Linux, a handle is called a file descriptor (fd) and it’s local to the process. The name “file descriptor” is just a name; it has nothing to do with files, nor does it describe anything.

Sockets are widely used in client-server architectures. The server listens for incoming connections, while the client initiates a connection to the server. Once connected, they can exchange data seamlessly.

Why Learn Socket Programming?

Socket programming powers many modern applications. Here are a few reasons to learn it:

Key Concepts to Understand

Before diving into code, let’s cover the basics:

Layers of protocols

Abstract idea: Network protocols are divided into layers. A lower layer can contain a higher layer as payload, and the higher layer adds new functions.

Reality: Ethernet contains IP, IP contains UDP or TCP, UDP or TCP contains application protocols.

We can also divide the layers by function:

  1. The layer of small, discrete messages (IP): When downloading a large file, network hardware can only process smaller units called IP packets — it cannot store the entire file at once. This is why the lowest layer operates on packets. TCP, a higher layer protocol, handles the task of reassembling these packets into complete application data.
  2. The layer of multiplexing (port number): Multiple apps can share the same network on a single computer. How does the computer know which packet belongs to which app? This is called demultiplexing. The next layer of IP (UDP or TCP) adds a 16-bit port number to distinguish different apps. Each app must claim an unused local port number before it can send or receive data. The computer uses the 4-tuple to identify a “flow” of information: (src_ip, src_port, dst_ip, dst_port)
  3. The layer of reliable and ordered bytes (TCP): TCP provides a layer of reliable & ordered bytes on top of IP packets, it handles retransmission, reordering automatically.
Level Subject Function
Higher TCP Reliable & ordered bytes
Middle Port in TCP/UDP Multiplex to programs
Lower IP Small & discrete messages

What’s actually relevant to us

The layers above IP are what we care about. Applications use TCP or UDP, either directly by rolling their own protocol, or indirectly by using an implementation of a well-known protocol. Both TCP and UDP are contained by IP. Everything is built on top of TCP or UDP.

Ethernet is below IP, it’s also packet-based but uses a different type of address (MAC).

Listening socket and connection socket

Listening is telling the OS that an app is ready to accept TCP connections from a given port. The OS then returns a socket handle for apps to refer to that port. From the listening socket, apps can retrieve (accept) incoming TCP connections, which is also represented as a socket handle. So there are 2 types of handles: listening socket & connection socket.

Creating a listening socket requires at least 3 API calls:

  1. Obtain a socket handle via socket().
  2. Set the listening IP:port via bind().
  3. Create the listening socket via listen().
fd = socket()  
bind(fd, address)  
listen(fd)  
while True:  
    conn_fd = accept(fd)  
    do_something_with(conn_fd)  
    close(conn_fd)

In summary, this code sets up a basic server that listens for incoming connections, accepts them in a loop, processes them (via a placeholder function), and then closes each connection afterwards.

Connect from a client

A connection socket is created from the client side with 2 API calls:

  1. Obtain a socket handle via socket().
  2. Create the connection socket via connect().
fd = socket()  
connect(fd, address)  
do_something_with(fd)  
close(fd)

socket() creates a typeless socket; the socket type (listening or connection) is determined after the listen() or connect() call. The bind() between socket() and listen() merely sets a parameter.

A Simple Example in Python

Python’s socket library makes it easy to experiment with socket programming. Below, we’ll create a basic client-server setup where the server listens for messages and the client sends a “Hello” message. You can run these scripts on your local machine to see sockets in action.

server.py

import socket  
  
# Create a socket  
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
host = '127.0.0.1'  # Localhost  
port = 12345  
  
# Bind the socket to an address and port  
server_socket.bind((host, port))  
  
# Listen for incoming connections  
server_socket.listen(5)  
print("Server listening on port", port)  
  
# Accept a connection  
client_socket, addr = server_socket.accept()  
print("Connected to client:", addr)  
  
# Receive data from the client  
data = client_socket.recv(1024).decode()  
print("Received:", data)  
  
# Close the connection  
client_socket.close()  
server_socket.close()

client.py

import socket  
  
# Create a socket  
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
host = '127.0.0.1'  # Localhost  
port = 12345  
  
# Connect to the server  
client_socket.connect((host, port))  
  
# Send a message  
message = "Hello!"  
client_socket.send(message.encode())  
  
# Close the connection  
client_socket.close()

How to run this example

  1. Open two terminal windows.
  2. In the first, run the server script with python server.py.
  3. In the second, run the client script with python client.py.
  4. Watch the server terminal display the “Hello!” message sent by the client.

This simple setup demonstrates the core of socket programming: establishing a connection and exchanging data.

Tips for Beginners

Note: C++ provides low-level control over socket programming through libraries like <sys/socket.h> on Unix-based systems (Linux/Mac) or Winsock on Windows. Python is too high-level for coding data structures like hashtables, because it’s built-in. Production stuff is mostly C with Python glue. Python only has a thin wrapper for socket, so the networking lessons are still suitable.

Wrapping Up

Socket programming opens the door to creating powerful, real-time applications. ...

Sources I took help from:

  1. https://beej.us/guide/bgnet
  2. https://build-your-own.org
  3. https://hypnotic-single-224.notion.site/Socket-programming-1966392011f080fdb3bfd6b1adb7722d