Skip to content

What is a computer network?

Open two terminals on two different machines, run ping from one toward the other, and you'll see replies come back in a few milliseconds. Nothing about that feels remarkable today, but it hides a genuinely hard engineering problem: how do two independent computers, built by different vendors, running different operating systems, agree on how to exchange bits over a wire or a radio signal they don't control?

That's what computer networking is actually about. Not cables and blinking lights, but agreement — a shared set of rules that lets machines that have never met before understand each other well enough to move data reliably.

A computer network is a group of two or more devices — called hosts or nodes — connected in a way that lets them exchange data. That's the whole definition, and it's deliberately broad: two laptops linked by a single Ethernet cable already qualify as a network, and so does the collection of billions of devices we call the internet.

Three things have to exist before any exchange is possible:

  1. A physical or wireless path — copper cable, fiber, or a radio link — that the electrical, optical, or electromagnetic signal can actually travel across.
  2. Addressing — a way to say "this data is for that specific machine," not just a way to shout into an ether where everyone could grab it.
  3. A protocol — a shared, precisely specified set of rules both sides agree to follow, covering everything from how a "1" bit is represented electrically to how a web page request is formatted.

Miss any one of the three and nothing works. A cable with no addressing scheme is a private line between exactly two devices with no way to reach anyone else. Addressing without a shared protocol is like having someone's mailing address but writing to them in a language they've never seen — the envelope gets there, but the content is useless. This module spends almost all of its time on addressing, and the module after it on protocols, because everything that comes later in the course is built on top of those two ideas.

Why networks exist: the client-server model

Before networks were common, an application and all its data lived on one machine. That worked fine until the machine wasn't powerful enough, or until you wanted many people to use the same application without giving each of them a full copy of it and its data.

The fix was to split the application into two roles:

  • A server — a machine with the resources (CPU, RAM, disk, a stable connection) to do the expensive work: running the database, storing files, executing business logic.
  • A client — a lighter machine, sometimes a phone, sometimes a browser tab, that asks the server to do that work and displays the result.

This is the client-server model, and it's the backbone of the modern internet. Your browser is a client; the machine serving this page is a server. A mobile banking app is a client; the bank's transaction system is a server. Even a curl command run from a terminal is acting as a client.

The model has a real, practical payoff: a client no longer needs the dependencies the work requires. If talking to a database means installing a specific driver and keeping it patched, that burden sits on the server, not on every device that wants to use the app. One server can also answer requests from thousands of clients at once, so the expensive hardware gets shared instead of duplicated on every desk.

Not every network conversation is client-server. Two peers can exchange data as equals — that's the idea behind peer-to-peer (P2P) protocols like BitTorrent, where every participant can act as both a client and a server for different pieces of a file. But client-server is overwhelmingly the pattern you'll meet in web development, backend systems, and cloud infrastructure, so it's the one this course assumes by default unless stated otherwise.

What actually happens when a client "talks" to a server

It helps to walk through this once at a high level before the later modules go deep on each piece, because it explains why so many separate technologies exist at all.

Client                                  Server
  |                                        |
  |-- 1. Find the server's address ------->|   (DNS)
  |-- 2. Establish a connection ---------->|   (TCP handshake)
  |-- 3. Send a request ------------------>|   (HTTP, or another protocol)
  |<-- 4. Receive a response --------------|
  |-- 5. Close or reuse the connection --->|
  • Finding the address. Humans use names like example.com; machines route traffic using numeric addresses. Something has to translate one into the other, and that something is DNS — the internet's distributed directory mapping names to the addresses behind them.
  • Establishing a connection. Before any application data moves, the two hosts usually agree they're both ready and able to talk, exchanging a short fixed sequence of messages called a handshake. This step belongs to TCP, the protocol that sets up the connection and guarantees delivery. Its counterpart, UDP, skips the handshake entirely and starts sending data immediately, trading that guarantee for speed — which is why this step in the diagram doesn't apply to UDP traffic at all.
  • Sending a request and getting a response. This is where application-level protocols live — HTTP for web pages, SMTP for mail, and so on.
  • Tearing down or reusing the connection. Connections aren't free to keep open forever. Closing one cleanly — so both sides agree it's finished and neither is left holding resources for a conversation that ended — matters just as much as opening it.

None of those steps are optional, and none of them happen "inside the network" in some abstract sense — every one of them is a specific exchange of bytes, following a specific protocol, that you can capture and inspect with a packet-capture tool. That's a theme worth internalizing early: a network isn't a black box. Everything it does is observable if you know where to look, and this course will have you looking early and often.

Layers: why this isn't one giant protocol

You might reasonably ask why we need DNS, TCP, and HTTP as separate things instead of one protocol that does it all. The answer is separation of concerns: the way bits travel across a copper wire has nothing to do with how a web server should format a response, and bundling those decisions together would mean redesigning everything every time one piece changes.

Instead, networking is built in layers, each responsible for one job and relying on the layer below it to have already done its job. A physical layer worries about voltages and light pulses. A layer above it worries about delivering a frame to the right host on a local network. A layer above that worries about getting a packet across the entire internet. And a layer above that worries about turning a byte stream into something an application understands, like an HTTP response.

This layering is formalized in two models you'll use constantly for the rest of this course: the OSI model and the TCP/IP model. Rather than introduce them here, they get a dedicated, careful treatment in OSI model (7 layers) and TCP/IP model, because getting the layer boundaries right is the single most useful mental model in all of networking. Every time you troubleshoot a connectivity issue later in this course, the first useful question will be "which layer is this failing at?"

Watching the client-server exchange actually happen

The exchange diagrammed above isn't a metaphor — you can build the smallest possible version of it in a few lines of Python and watch the layers do their job.

# server.py — listens on all interfaces, port 9000
import socket

srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("0.0.0.0", 9000))
srv.listen(1)
print("listening on 0.0.0.0:9000")

conn, addr = srv.accept()
print("client connected from", addr)
data = conn.recv(1024)
print("received:", data.decode())
conn.sendall(b"hello from the server\n")
conn.close()
# client.py — connects to one specific server:port
import socket

cli = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
cli.connect(("127.0.0.1", 9000))
cli.sendall(b"hello from the client\n")
print(cli.recv(1024).decode())
cli.close()

Run python3 server.py in one terminal and python3 client.py in another (same machine, or point the client at the server's LAN address once it's bound to 0.0.0.0 instead of a loopback-only address). Two lines of output tell you the whole story:

listening on 0.0.0.0:9000
client connected from ('127.0.0.1', 54212)

bind() is the server claiming a socket — an address-plus-port pair — before anyone can reach it. listen() puts that socket into a state where the kernel will queue incoming connection attempts instead of rejecting them. accept() is what turns one of those queued attempts into an actual connected socket, distinct from the listening one, which is exactly why a busy server can accept thousands of clients on the same port: each accepted connection gets its own socket, identified by the pair of addresses and ports involved, while the original listening socket keeps waiting for the next one.

You can confirm the listening socket exists, independent of the Python process's own print statement, with ss:

ss -tln
State  Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0      1            0.0.0.0:9000       0.0.0.0:*

That line exists the moment listen() runs and disappears the moment the process exits or crashes — which makes ss -tln the fastest way to answer "is anything actually listening" without trusting a log line that might be stale or from a different process entirely.

Explain it in 30 seconds

If an interviewer asks you to describe the client-server model without notes: a server binds to an address and port and waits; a client initiates a connection to that specific address and port; once connected, both sides exchange data over that one socket pair until either side closes it. The server can hold many such connections open at once because each is identified by the full four-tuple — source IP, source port, destination IP, destination port — not just the port number alone. Everything above that (HTTP, SSH, a custom protocol) is just an agreement about what bytes to put on top of that already-established channel.

Practical scenario: the API is "down"

A developer says the payment API is down because the application logs show connection timed out. That sentence is not enough to diagnose anything. "Down" could mean several different failures:

Symptom                             First question to ask
----------------------------------  -----------------------------------------
No Wi-Fi or unplugged cable         Is there a working physical or radio link?
Wrong IP address or subnet          Can packets reach the other network?
DNS name does not resolve           Can the client find the server's address?
Port 443 closed or filtered         Is the server process reachable?
HTTP 500 after a successful connect Is the application failing after the network worked?

That is why this vocabulary matters even for backend work. A timeout is not automatically an application bug, and a successful ping is not proof that an API is healthy. Good troubleshooting narrows the failure layer by layer: link, address, name resolution, transport connection, then application response. The rest of this module gives names to those pieces so later commands such as ip addr, ss, dig, curl, and packet captures have somewhere to fit in your head.

Where beginners go wrong

  • Treating "the internet" and "a network" as different things. The internet is a network — an enormous one, made of many smaller networks connected together. The concepts you learn on a two-host LAN apply directly to it.
  • Assuming a network needs wires. Wi-Fi, cellular, and satellite links are all valid physical layers. What makes something a network is the addressing and protocol agreement, not the medium.
  • Confusing the client-server model with a specific technology. It's an architectural pattern, not a protocol or product. HTTP happens to be client-server; so is SSH; so is a database connection.
  • Assuming every device you can ping is "on the network" in a useful sense. Physical connectivity is necessary but not sufficient — a device also needs proper addressing and a protocol both sides understand before it can do anything useful. This distinction becomes concrete once you reach IP addressing.

Try it yourself

  1. Pick any website you use daily. List, in order, the client-server exchanges you think must happen between typing the URL and seeing the fully loaded page. Don't worry about getting protocol names exactly right yet — focus on the sequence of events.
  2. Identify one application you use that is peer-to-peer rather than client-server (a video call, a torrent client, a mesh chat app). What would change about it if it were redesigned as strict client-server?
  3. On a machine with ping installed, run ping -c 4 <a domain name you use often> and ping -c 4 <its numeric IP, found by any means you like>. Both should succeed. What does that tell you about where the "address translation" step happens relative to the actual data exchange?
  4. Take the three requirements from the top of this article — a path, addressing, and a protocol — and decide which one is missing in each case: a laptop plugged into a switch but with no IP address configured; two machines with valid addresses on networks that have no route between them; a client sending JSON to a server that only accepts a binary format.

That second case in exercise 4 is the interesting one. A path exists, both hosts have addresses, and still nothing arrives — because addresses only work when both machines can be located relative to each other, and that depends on how addresses are grouped into networks. Grouping, in turn, depends on how much ground a network covers: one room, one campus, or one continent. Types of networks starts there.

Sources