Client-Server Communication
Master how computers talk to each other. Understand TCP connections, HTTP requests, and WebSockets—the protocols that power every app you use daily.
When you open Instagram, your phone talks to a . When you send a message, data travels across the internet. These protocols make it all work.
EXERCISE
1Understanding Client and Server
One machine asks, another delivers. This simple pattern powers the entire internet.
The Basic Idea
Client: The one making requests. Your phone, laptop, browser.
Server: The one doing the work. Handles business logic, stores data, runs computations.
Pattern: Client demands. Server delivers.
Real Examples
Opening Instagram:
Client (your phone): "Show me my feed"
Server (Instagram backend): Fetches posts from , returns them
Deleting a tweet:
Client (browser): "Delete tweet ID 12345"
Server (Twitter backend): Removes from database, confirms deletion
Sending email:
Client (Gmail app): "Send this email to user@example.com"
Server (Gmail backend): Queues email, sends it, returns success
Booking Uber:
Client (Uber app): "Request ride from point A to B"
Server (Uber backend): Matches driver, updates database, pushes notification
Every app works this way.
Why This Model Wins
Centralized control: Update server once. All clients benefit immediately.
Security: Sensitive operations happen on server. Client never touches database directly.
Example: Banking app.
Your phone shows balance. But it cannot directly modify the database.
Server validates identity, checks permissions, executes transaction, updates records.
Client only sees results. Database stays protected.
Separation of concerns: Client handles UI. Server handles logic and data.
Scale: One server handles thousands of clients simultaneously.
Communication Happens Over Networks
Two machines must talk. They could be:
- Your laptop → AWS server (across internet)
- Two servers in same (local network)
- Mobile app → server (cellular network)
Data travels as packets over TCP/IP protocol.
Physical distance matters:
Server in same city? 10ms latency.
Server across country? 50ms latency.
Server on another continent? 200ms latency.
This is why CDNs exist. Content delivered from nearest server.
The Alternative: Peer-to-Peer
Peer-to-peer: Clients talk directly to each other. No central server.
Example: BitTorrent. You download video chunks from other users directly.
Why not always use this?
Complexity: Clients must discover each other, coordinate, handle security.
Trust: Cannot trust random peers. Who validates data correctness?
Consistency: How does everyone see the same version of data?
Most apps choose client-server for simplicity and control.
The Critical Question
How do client and server actually exchange data?
They need a common language. Just like humans need English or Hindi.
Computers need protocols: TCP, HTTP, .
Understanding these is understanding the internet.
EXERCISE
2TCP: Reliable Data Transfer
Before HTTP or WebSockets, there is TCP. Learn how connections work and why they are expensive.
What Is TCP?
TCP (Transmission Control Protocol): The way to send data reliably over networks.
Guarantees:
- Data arrives in correct order
- No data lost
- No duplicates
- Failed packets retransmitted automatically
Almost every app uses TCP because reliability matters.
Alternative is UDP: Faster but unreliable. Used for video calls, gaming. Packets can arrive out of order or get lost.
The Three-Way Handshake
Before any data flows, TCP requires setup.
Process:
Step 1: Client → Server: "SYN" (let us connect)
Step 2: Server → Client: "SYN-ACK" (agreed, let us connect)
Step 3: Client → Server: "ACK" (connection established)
Now data can flow.
Visualization:
Client Server
| |
|-------- SYN ----------->|
|<------ SYN-ACK ---------|
|-------- ACK ----------->|
| |
[Connection Ready]
Why This Is Expensive
Each step is a network round-trip.
Example: Client in Mumbai. Server in California. 200ms latency per trip.
Three-way handshake = 3 messages = 600ms before sending any data!
For a single HTTP request: 600ms setup + actual request/response.
This is why connection reuse matters.
The Two-Way Teardown
When done, connection closes.
Process:
Step 1: Client → Server: "FIN" (finished, closing)
Step 2: Server → Client: "ACK" (acknowledged, connection closed)
Sometimes: Server also sends FIN, client sends ACK (four-way).
Typical: Two messages to close connection.
Connections Do Not Auto-Close
Critical fact: TCP connection does NOT automatically close after one request.
Connection stays open until:
- Either party explicitly closes it
- Network interruption (router dies, cable unplugged)
- Timeout from inactivity (configured, often 60 seconds)
This matters: You can reuse one TCP connection for multiple requests!
Connection Reuse: The Performance Win
Without reuse (new connection per request):
Request 1: 3-way handshake + request + response + 2-way teardown
Request 2: 3-way handshake + request + response + 2-way teardown
Request 3: 3-way handshake + request + response + 2-way teardown
Overhead: 15 network messages for 3 requests.
With reuse (keep connection open):
First request: 3-way handshake + request + response
Request 2: request + response (same connection)
Request 3: request + response (same connection)
Final: 2-way teardown
Overhead: 5 network messages total. 3× faster!
Real-World Impact
Scenario: Mobile app loading profile. Needs 5 API calls.
Without reuse:
- Setup: 5 × 3 messages = 15 messages
- Teardown: 5 × 2 messages = 10 messages
- Total: 25 messages overhead
With reuse:
- Setup: 1 × 3 messages = 3 messages
- Teardown: 1 × 2 messages = 2 messages
- Total: 5 messages overhead
5× reduction! This is why connection pooling exists.
TCP Just Delivers Bytes
Important: TCP handles reliable delivery. It does NOT care what data you send.
Analogy: TCP is like postal service. Delivers letters reliably. Does not read content.
What you send over TCP: Totally up to you.
Common choices:
- HTTP (most web apps)
- Custom protocols (, databases)
- WebSockets (real-time apps)
TCP delivers bytes. You define what those bytes mean.
Example: Redis Does Not Use HTTP
Redis uses custom protocol over TCP.
Why? Optimized for key-value operations. Faster than HTTP for its use case.
Takeaway: You can define your own protocol. Just ensure both sides understand it.
When TCP Is Not Used
Video calls (Zoom): Use UDP. Speed matters more than perfection. Dropped frame = minor glitch.
Gaming (Fortnite): Use UDP. Old position data is worthless. Need instant updates.
DNS lookups: Often UDP. Single packet request/response. No need for connection.
Everything else: Probably TCP. Reliability worth the overhead.
EXERCISE
3HTTP: How the Web Talks
TCP delivers data. HTTP defines what that data means. Learn the protocol powering every website and API.
What Is HTTP?
HTTP (HyperText Transfer Protocol): The common language of the web.
Purpose: Defines how to format requests and responses.
Runs on TCP: HTTP uses TCP for reliable delivery.
Most APIs you build: using HTTP.
HTTP Request Format
Structure:
GET /api/users/123 HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0
Accept: application/json
(optional body)
Parts:
Request line: Method (GET), path (/api/users/123), version (HTTP/1.1)
Headers: Key-value metadata (Host, User-Agent, Accept)
Body (optional): Data sent to server (, form data)
HTTP Methods
GET: Retrieve data. No body.
POST: Create resource. Has body.
PUT: Update entire resource. Has body.
DELETE: Remove resource. Usually no body.
PATCH: Partial update. Has body.
Example GET:
GET /api/products/456 HTTP/1.1
Host: store.com
Server returns product with ID 456.
Example POST:
POST /api/products HTTP/1.1
Host: store.com
Content-Type: application/json
{"name": "Laptop", "price": 999}
Server creates product, returns it with new ID.
HTTP Response Format
Structure:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 87
{"id": 123, "name": "John", "email": "john@example.com"}
Parts:
Status line: Version, status code (200), message (OK)
Headers: Content-Type, Content-Length, etc.
Body: Actual data (JSON, HTML, image bytes)
HTTP Status Codes
2xx Success:
- 200 OK: Request succeeded
- 201 Created: Resource created
- 204 No Content: Success, no body
4xx Client Errors:
- 400 Bad Request: Invalid syntax
- 401 Unauthorized: Auth required
- 404 Not Found: Resource missing
- 429 Too Many Requests: Rate limited
5xx Server Errors:
- 500 Internal Server Error: Server crashed
- 502 Bad Gateway: Upstream failed
- 503 Service Unavailable: Overloaded
The Connection Problem
HTTP/1.1 default behavior: Connection closes after response.
Flow:
- TCP 3-way handshake
- Send HTTP request
- Receive response
- TCP 2-way teardown
For next request: Repeat entire flow!
Why? HTTP designed for simple document retrieval. One request per page.
Modern reality: Page load needs 50-100 requests (HTML, CSS, JS, images, API calls).
Problem: New TCP connection per request is extremely expensive.
The Solution: Keep-Alive Header
Tell server to keep connection open.
Request:
GET /api/data HTTP/1.1
Host: api.example.com
Connection: keep-alive
Response:
HTTP/1.1 200 OK
Connection: keep-alive
(data)
Connection stays open. Next request reuses it. No new handshake.
Modern browsers: Automatically include keep-alive.
Modern servers (, Apache): Support it by default.
Connection Pooling
Backend services maintain pool of persistent connections.
Example: app → Database.
Without pooling: New TCP connection per query. Slow.
With pooling: Maintain 10 persistent connections. Reuse them. Fast.
Why HTTP Dominates
Universal: Every language has HTTP libraries.
Human readable: Debug with curl, Postman, browser tools.
Stateless: Each request independent. Easy to scale.
Standardized: Everyone understands GET, POST, status codes.
HTTP is the shared language of the internet.
EXERCISE
4WebSockets: When HTTP Is Not Enough
HTTP is request-response only. WebSockets enable servers to push data to clients instantly. This is how real-time apps work.
The HTTP Limitation
HTTP is one-way: Client always initiates. Server only responds.
Server cannot push data without client requesting first.
Problem: How to build real-time ?
Examples:
- Chat apps (messages arrive instantly)
- Live notifications (new like, new follower)
- Stock tickers (prices update every second)
- Collaborative editing (Google Docs)
- Live sports scores
The Bad Solution: Polling
Short polling: Client repeatedly asks "any updates?"
Every 2 seconds:
Client: "Any new messages?"
Server: "No"
Client: "Any new messages?"
Server: "No"
Client: "Any new messages?"
Server: "Yes: {message}"
Problems:
- Wasteful: 99% requests return nothing
- Latency: Up to 2 second delay
- Server load: Thousands of clients polling = millions of wasted requests
WebSockets: The Real Solution
WebSocket: Persistent, bidirectional connection.
Key feature: After setup, either side can send data anytime.
Flow:
- Client starts WebSocket handshake (over HTTP)
- Connection upgrades to WebSocket
- Both sides send messages freely
- Connection stays open until closed
WebSocket Handshake
Client request:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Server response:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Connection upgraded. Now WebSocket protocol. No more HTTP.
Communication Flow
Client Server
| |
|--- HTTP Upgrade ------->|
|<-- 101 Switching --------|
| |
|=== WebSocket Open ===|
| |
|--- "Hello" ------------>|
|<-- "Hi there" ----------|
|<-- "New notification" --|
|--- "Got it" ----------->|
After upgrade: Messages flow freely. No request/response pattern.
Performance Comparison
Scenario: Chat app. Sending 10 messages.
HTTP (new connection each time):
Message 1: 3-way + request + response + 2-way = 5 messages
Message 2: 3-way + request + response + 2-way = 5 messages
...
Message 10: 3-way + request + response + 2-way = 5 messages
Total: 50 network messages
WebSocket:
Initial: 3-way handshake + upgrade
Message 1: Send (1 packet)
Message 2: Send (1 packet)
...
Message 10: Send (1 packet)
Final: Close
Total: 13 network messages
WebSocket is 4× more efficient!
Real-World Use Cases
Chat apps (WhatsApp, Slack):
Messages arrive instantly. No polling needed.
Server pushes message to recipient via WebSocket.
Live notifications (Instagram, Twitter):
New like? Server pushes instantly.
No need for app to constantly ask "any updates?"
Stock trading (Robinhood, Zerodha):
Prices update multiple times per second.
Server streams price updates continuously.
Collaborative editing (Google Docs, Figma):
See others typing in real-time.
Every keystroke sent via WebSocket, broadcast to all users.
Live sports (ESPN apps):
Goal scored? See it within 1 second. No refresh needed.
The Cost of WebSockets
Persistent connections are expensive.
Memory: Each connection holds server resources (TCP socket, buffers).
100,000 users = 100,000 open connections.
Server requirements: Need specialized servers for high connection counts (Node.js, Go, Erlang).
Traditional servers (Apache): Designed for short HTTP requests. Poor WebSocket performance.
Trade-off: A much better user experience, at a higher infrastructure cost.
When NOT to Use WebSockets
Simple CRUD operations: Fetching profile? Use HTTP. No need for persistent connection.
Infrequent updates: Notification once per hour? HTTP polling fine.
Public APIs: Hard to manage thousands of persistent connections from unknown clients.
Mobile on cellular: WebSocket connections interrupted by network switches. HTTP with retries more reliable.
Use WebSockets only when truly needed. For real-time, bidirectional communication.
Building with Socket.IO
Socket.IO: Popular library for WebSockets.
Features:
- Automatic reconnection
- Fallback to polling if WebSocket blocked
- Easy server and client setup
Chat example:
Server:
const io = require('socket.io')(3000);
io.on('connection', (socket) => {
socket.on('chat message', (msg) => {
io.emit('chat message', msg); // Broadcast
});
});
Client:
const socket = io('http://localhost:3000');
socket.emit('chat message', 'Hello!');
socket.on('chat message', (msg) => display(msg));
That is it! Basic real-time chat in under 10 lines.
