A complete deep-dive into how client–server connections are established, secured, attacked — and how Android's OkHttp masters them all.
Before any byte is sent, your device must translate a human-readable hostname into an IP address. This chain of delegated authority is called the Domain Name System.
TCP is a connection-oriented protocol. Before data flows, client and server must synchronize sequence numbers through a precise ritual — the 3-way handshake.
The client sends a TCP segment with the SYN flag set. It includes a randomly chosen Initial Sequence Number (ISN) — e.g., seq=1000. This number ensures packets are reassembled in order and prevents replay attacks. The server is now in SYN_RECEIVED state.
The server responds with both SYN and ACK flags set. It acknowledges the client's ISN (ack = x+1) and sends its own ISN (seq = y). This proves the server is alive and ready, and allows bidirectional sequence tracking.
The client moves to ESTABLISHED state after this.
The client sends a final ACK (ack = y+1), confirming it received the server's ISN. Both sides are now in ESTABLISHED state and can send data. The entire handshake takes 1 RTT (Round Trip Time) before any data flows.
This is why TLS 1.3's 0-RTT and TCP Fast Open were invented — to reduce this overhead for repeat connections.
Closing uses a 4-step FIN/ACK exchange — because TCP is full-duplex, each direction closes independently. Either side sends FIN → other ACKs → other sends FIN → original ACKer sends final ACK. The initiator enters TIME_WAIT for 2×MSL to handle stray packets.
OkHttp avoids this cost by keeping connections alive in a pool.
TLS (Transport Layer Security) builds an encrypted tunnel over TCP. It negotiates ciphers, authenticates the server via X.509 certificates, and derives shared session keys — all before a single byte of HTTP is sent.
TLS 1.2 requires 2 round trips after TCP to complete the handshake. Combined with TCP's 1 RTT, a fresh HTTPS connection costs 3 RTTs before the first HTTP byte. This is why connection reuse (keep-alive) and session resumption (session tickets / PSK) are critical optimizations.
| Cipher Suite | Key Exchange | Auth | Encryption | MAC | Forward Secrecy |
|---|---|---|---|---|---|
| TLS_AES_256_GCM_SHA384 | ECDHE | RSA/ECDSA | AES-256-GCM | SHA-384 | ✓ |
| TLS_CHACHA20_POLY1305_SHA256 | ECDHE | RSA/ECDSA | ChaCha20 | Poly1305 | ✓ |
| TLS_AES_128_GCM_SHA256 | ECDHE | RSA/ECDSA | AES-128-GCM | SHA-256 | ✓ |
| TLS_RSA_WITH_AES_256_CBC_SHA | RSA | RSA | AES-256-CBC | SHA-1 | ✗ Removed in 1.3 |
Forward Secrecy means that even if the server's private key is compromised in the future, past recorded sessions cannot be decrypted — because the session key was ephemeral (ECDHE). Without FS (RSA key exchange), a stolen private key unlocks all past traffic. This is why TLS 1.3 mandates ECDHE.
Every phase of the connection lifecycle has attack surfaces. Understanding these is essential to appreciating why TLS, certificate validation, and SSL pinning exist.
OkHttp is Square's HTTP client for Android and Java. It's the networking backbone of Retrofit, Picasso, and countless Android apps. Here's why it's the gold standard.
OkHttp manages DNS, socket creation, TLS, HTTP/1.1 and HTTP/2 multiplexing, connection pooling, retries, redirects, and gzip decompression — all transparently, through a layered interceptor chain.
Every request passes through a chain of interceptors — in order on the way out, reverse order on the way back. User interceptors fire first, network interceptors fire last.
Certificate pinning hardcodes the expected public key fingerprint of your server's certificate. Even if a rogue CA issues a valid cert for your domain, the pinned client will reject it.
Normal CA validation trusts any of ~130 root CAs pre-installed on Android. A government or attacker who can compromise one of those CAs — or install their own root (e.g. via MDM) — can issue a valid cert for your domain. Pinning ignores the system trust store and checks only your specific key. This is why banking apps, VPNs, and healthcare apps use it.
Don't pin if you don't control your certificate rotation process, or if you integrate third-party APIs (you can't predict their cert rotation). Don't pin for CDN-hosted assets where the cert changes per PoP. The risk of a broken app from a missed rotation often outweighs the benefit for low-sensitivity apps. Use network security config on Android for a declarative alternative.
OkHttp doesn't just implement HTTP — it aggressively optimizes every phase of the connection lifecycle to minimize latency and battery usage on mobile.
OkHttp maintains a ConnectionPool of idle HTTP/1.1 sockets and HTTP/2 connections. When you make a request, OkHttp checks if a pooled connection exists for that host:port pair. If yes — no DNS lookup, no TCP handshake, no TLS handshake. Just write the request.
Default: 5 connections max, 5 minutes keep-alive. HTTP/2 connections multiplex many requests over one socket, so often only 1 pooled connection per host is needed. Connections are evicted by a background cleanup task using GC root detection (no GC tricks — just reference counting).
HTTP/1.1 sends requests serially per connection (or uses multiple connections which wastes resources). HTTP/2 uses a single TCP connection and multiplexes many streams concurrently — each request is a stream with a unique ID. Server can push resources before the client asks. Headers are compressed with HPACK.
Effect: a single OkHttp connection to an HTTP/2 server can handle 100+ concurrent requests, vs 6 parallel connections for HTTP/1.1. This cuts mobile radio wake-up time (huge for battery life) and eliminates head-of-line blocking at the HTTP layer.
BridgeInterceptor automatically adds Accept-Encoding: gzip to outgoing requests. When the server responds with gzip-encoded body, OkHttp decompresses it transparently before returning to your code — you always see raw bytes. This typically reduces JSON response sizes by 60–80%, slashing bandwidth and parse time.
RetryAndFollowUpInterceptor handles connection failures, stale pooled connections (automatically retried with a fresh connection), 307/308 redirects, 401/407 authentication challenges, and 503 with Retry-After header. It enforces a maximum of 20 follow-ups to prevent infinite redirect loops.
For idempotent requests (GET, HEAD), OkHttp can retry on network failures. POST is not retried by default (not safe to duplicate).
OkHttp's CacheInterceptor implements RFC 7234 HTTP caching. Responses with Cache-Control, Expires, or ETag headers are stored in a size-bounded LRU disk cache. Cache-Control: max-age serves without network. ETags enable conditional requests (304 Not Modified) which skip transferring the body. You can force FORCE_CACHE for offline mode.
OkHttp implements Happy Eyeballs — when a hostname has both IPv4 and IPv6 addresses, it attempts connections in parallel (with a 250ms stagger for IPv6 preference) and uses whichever completes first. This ensures that broken IPv6 deployments don't add latency — the IPv4 fallback wins quickly. Users on IPv6 networks see reduced latency.
OkHttpClient holds the connection pool, thread pool, cache, and DNS resolver. Creating a new OkHttpClient per request destroys all pooling benefits and leaks threads. Use a single application-scoped instance (singleton, Dagger/Hilt, or Application class). Use newBuilder() to create lightweight variants that share the pool.
| Feature | OkHttp | HttpURLConnection | Volley | Ktor |
|---|---|---|---|---|
| HTTP/2 | ✓ Native | ✗ | ✗ | ✓ |
| Connection Pool | ✓ Built-in | Limited | ✓ | ✓ |
| TLS Config | Full control | Basic | Limited | Full control |
| Certificate Pinning | ✓ Built-in | Manual | Manual | Plugin |
| Interceptors | ✓ Powerful | ✗ | Limited | ✓ |
| Gzip auto | ✓ | Manual | ✓ | ✓ |
| Retrofit compat | ✓ Native | ✗ | ✗ | No |
| Used by | Retrofit, Picasso, Coil, Firebase | Legacy Android | Google apps | JetBrains |