IPv4 Addressing
Beginner to Intermediate
1 of 5
What is an IPv4 Address?
Every device connected to an IP network needs a unique identifier — this is the IP address. IPv4 (Internet Protocol version 4) uses a 32-bit address, which means there are 232 = about 4.3 billion possible addresses. These 32 bits are split into 4 groups of 8 bits each, written in dotted-decimal notation like 192.168.1.10.
Every IPv4 address has two logical parts: a Network ID (identifies which network the device belongs to) and a Host ID (identifies the specific device within that network). A subnet mask tells you where the network part ends and the host part begins.
An IPv4 address is 32 bits wide. It is divided into a Network ID portion and a Host ID portion. The split point is determined by the subnet mask.
| Network ID (24 bits) | Host ID (8 bits) | ||||||||||||||||||||||||||||||
| 192 | 168 | 1 | 10 | ||||||||||||||||||||||||||||
| Full Address: 192.168.1.10 | Subnet Mask: /24 = 255.255.255.0 | |||||||||||||||||||||||||||||||
In CIDR notation (Classless Inter-Domain Routing), the address is written as 192.168.1.10/24 where /24 means the first 24 bits form the Network ID. This gives 254 usable host addresses (256 minus 2 reserved).
In any subnet, two addresses are always reserved and cannot be assigned to any host:
| Address | Example (in /24 network) | Meaning |
|---|---|---|
| Network Address (Host ID = all 0s) |
204.152.189.0 | Identifies the network itself. Cannot be assigned to a host. |
| Broadcast Address (Host ID = all 1s) |
204.152.189.255 | Sends a packet to ALL hosts on the subnet simultaneously. |
For the network 204.152.189.0/24, valid host addresses run from 204.152.189.1 to 204.152.189.254 — that is 254 usable addresses.
| Address | C Constant | Purpose | Use Case |
|---|---|---|---|
| 127.0.0.1 | INADDR_LOOPBACK | Loopback address (localhost) | Test client-server on same machine. Packet never leaves the host. |
| 0.0.0.0 | INADDR_ANY | Wildcard address | Server listens on ALL network interfaces of a multihomed host. |
| x.x.x.255 | – | Broadcast address | Send to all hosts on a subnet simultaneously. |
Loopback Address in Action
When you send data to 127.0.0.1, the kernel never places the packet on the wire. It loops it back internally. This is extremely useful when developing and testing socket programs — both the client and server run on the same machine.
Wildcard Address — INADDR_ANY
A multihomed host is a computer with multiple network interfaces (e.g., eth0 with 192.168.1.5 and eth1 with 10.0.0.5). If a server binds to a specific IP, it only receives packets arriving on that interface. Binding to INADDR_ANY (0.0.0.0) allows the server to receive packets from any of the host’s network interfaces.
| Client A 192.168.1.100 |
→ | Multihomed Server
eth0: 192.168.1.5 Bound to INADDR_ANY |
|
| Client B 10.0.0.20 |
→ |
Subnetting allows an organization to divide its assigned IP block into smaller sub-networks. Instead of having one big flat network, you create multiple smaller segments (subnets), each identified by an extended network ID = Network ID + Subnet ID.
| Network ID (24 bits) | Subnet ID (4 bits) | Host ID (4 bits) | |||||||||||||||||||||||||||||
| 204 | 152 | 189 | 0001 | 0000 | |||||||||||||||||||||||||||
| Extended Network ID = 204.152.189.16/28 (Subnet 1 = 0001, Host part = 0000) | Host | ||||||||||||||||||||||||||||||
In this example, we took the assigned block 204.152.189.0/24 and split the 8-bit Host ID into a 4-bit Subnet ID and a 4-bit Host ID. The subnet mask becomes /28 (28 leading 1s = 255.255.255.240).
Subnets Created
| Subnet ID (4 bits) | Network Address | Usable Range | Broadcast |
|---|---|---|---|
| 0001 (1) | 204.152.189.16/28 | .17 – .30 | 204.152.189.31 |
| 0010 (2) | 204.152.189.32/28 | .33 – .46 | 204.152.189.47 |
| … (up to 14) | … | … | … |
In Linux socket programming, these constants are defined in <netinet/in.h>. Here is how they are used when creating a TCP server:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define PORT 8080
int main() {
int server_fd;
struct sockaddr_in addr;
/* Step 1: Create a TCP socket */
server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket");
exit(EXIT_FAILURE);
}
/* Step 2: Fill in address structure */
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
/*
* INADDR_ANY = 0.0.0.0
* The server will accept connections on ALL interfaces.
* Change to INADDR_LOOPBACK (127.0.0.1) to accept
* only local (loopback) connections.
*/
addr.sin_addr.s_addr = htonl(INADDR_ANY);
/* OR: addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); */
/* Step 3: Bind the socket to the address */
if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("bind");
close(server_fd);
exit(EXIT_FAILURE);
}
printf("Server listening on ALL interfaces, port %d\n", PORT);
/* Step 4: Listen and accept (simplified) */
listen(server_fd, 5);
/* ... accept() loop goes here ... */
close(server_fd);
return 0;
}
Key points:
htonl()converts the constant from host byte order to network byte order (big-endian).AF_INETspecifies IPv4. UseAF_INET6for IPv6.INADDR_ANYbinds to all interfaces — ideal for production servers.INADDR_LOOPBACKrestricts to local connections — ideal for testing.
INADDR_ANY (0.0.0.0) is the IPv4 wildcard address. When a server binds to it, the server accepts incoming connections on all network interfaces of the host. This is important on multihomed hosts (multiple NICs) so clients connecting via any interface can be served. Without it, the server would only listen on one specific IP address.
127.0.0.1 (hostname: localhost), defined by constant INADDR_LOOPBACK. When a packet is sent to this address, the Linux kernel never transmits it on the wire — it immediately loops the data back as input to the same host. This allows testing client-server applications without any physical network.
htonl(INADDR_ANY) to convert it to network byte order (big-endian). The sin_addr.s_addr field in struct sockaddr_in expects a 32-bit value in network byte order. Although INADDR_ANY is 0 (and byte order doesn’t matter for zero), always using htonl() is correct practice.
Continue Learning
Next up: IPv6 Addressing — 128-bit addresses, compressed notation, and IPv4-mapped addresses.
