Networking Basics for Devs

beginner networking tcp udp ip-address ports

We don’t need to be network engineers, but understanding the basics of how data moves across the internet is essential. Every time we deploy an app, debug a connection issue, or configure a firewall, we’re dealing with networking concepts.

IP Addresses

An IP address is like a street address for a device on a network. There are two versions:

IPv4 — The classic format. Four numbers separated by dots, each between 0 and 255. Example: 192.168.1.10. There are about 4.3 billion possible addresses, and we’ve basically run out.

IPv6 — The newer format. Eight groups of hexadecimal digits separated by colons. Example: 2001:0db8:85a3:0000:0000:8a2e:0370:7334. There are enough IPv6 addresses for every grain of sand on Earth to have billions of them.

Private vs Public IP Ranges

Not all IPs are routable on the public internet. Some ranges are reserved for private networks (like our home Wi-Fi or office LAN):

  • 10.0.0.0 to 10.255.255.255 — large networks, often used in cloud/VPC setups
  • 172.16.0.0 to 172.31.255.255 — medium networks
  • 192.168.0.0 to 192.168.255.255 — home routers, the one we see most often

Our router gets one public IP from the ISP and hands out private IPs to all our devices. This is called NAT (Network Address Translation).

Ports

If an IP address is the street address of a building, a port is the apartment number. A single server can run multiple services, and each one listens on a different port.

Ports range from 0 to 65535. Here are the ones we’ll run into constantly:

PortServiceNotes
22SSHRemote access to servers
80HTTPUnencrypted web traffic
443HTTPSEncrypted web traffic
3000Dev serversExpress, Next.js, Vite defaults
5432PostgreSQLDefault Postgres port
6379RedisDefault Redis port
8080Alt HTTPCommon alternative for HTTP
27017MongoDBDefault Mongo port
# Check what's listening on a specific port
lsof -i :3000          # macOS/Linux — who's using port 3000?
netstat -tlnp          # Linux — list all listening ports

# Kill a process on a specific port (macOS)
lsof -ti :3000 | xargs kill -9

TCP vs UDP

These are the two main transport protocols. They sit on top of IP and determine how data is delivered.

TCP (Transmission Control Protocol) — Reliable and ordered. It sets up a connection first (the “three-way handshake”), makes sure every packet arrives, and reassembles them in order. If a packet is lost, it retransmits it. This is what HTTP, SSH, email, and database connections use.

UDP (User Datagram Protocol) — Fast but unreliable. No connection setup, no guarantee packets arrive, no ordering. Just fire and forget. This is what video calls, online gaming, DNS queries, and live streaming use — situations where speed matters more than perfection.

TCP: "Hey, are you there?" → "Yes" → "OK, sending data" → data → "Got it?" → "Yes"
UDP: data → data → data → data (hope you got it!)

What Happens When We Type a URL

This is the classic interview question. Let’s walk through what actually happens when we type https://pman47.cc and hit Enter:

1.
DNS Lookup
pman47.cc → 144.24.126.230
2.
TCP Handshake
SYN → SYN-ACK → ACK (3-way)
3.
TLS Handshake
negotiate encryption (HTTPS only)
4.
HTTP Request
GET / HTTP/1.1
5.
Server Response
200 OK + HTML content
6.
Browser Renders
parse HTML → fetch CSS/JS → paint page

All of this happens in milliseconds. The browser also fetches additional resources (CSS, JS, images) as it parses the HTML, often in parallel.

localhost, 0.0.0.0, and 127.0.0.1

These three come up all the time in development and they’re subtly different:

  • 127.0.0.1 — The loopback address. Traffic sent here never leaves the machine. It always refers to “this computer.”
  • localhost — A hostname that typically resolves to 127.0.0.1 (configured in /etc/hosts). On some systems it might resolve to the IPv6 loopback ::1 instead.
  • 0.0.0.0 — Means “all network interfaces.” When a server binds to 0.0.0.0, it listens on every available interface — loopback, Wi-Fi, Ethernet, everything. This is important in Docker, where binding to 127.0.0.1 means the container can’t be reached from outside.
# This only accepts connections from the same machine
node server.js --host 127.0.0.1

# This accepts connections from anywhere (needed in Docker)
node server.js --host 0.0.0.0

# Check what a hostname resolves to
getent hosts localhost
# 127.0.0.1       localhost

A common Docker gotcha: our app starts fine but we can’t reach it from the host machine. Nine times out of ten, it’s because the app is bound to 127.0.0.1 instead of 0.0.0.0.

In simple language, data travels across the internet using IP addresses to find the right machine and ports to find the right service — with TCP making sure nothing gets lost along the way.