Mastering TCP, HTTP, Sockets, and Socket Connection Pools
This article walks developers through the OSI model, explains TCP's three‑way handshake and four‑way termination, contrasts TCP with UDP, addresses common networking questions, and details how to implement long‑lived socket connections and a reusable socket connection pool in Node.js.
As developers frequently encounter terms like HTTP, TCP/IP, UDP, Socket, long‑lived Socket, and Socket connection pool, this article starts from basic network protocol concepts and progressively explains their relationships.
OSI Seven‑Layer Model
The OSI model divides network communication into seven layers: Physical, Data Link, Network, Transport, Session, Presentation, and Application. IP resides in the Network layer, TCP and UDP in the Transport layer, and HTTP in the Application layer. The model does not define Socket, which is introduced later with code examples.
TCP and UDP Connections
TCP establishes a connection via a three‑way handshake and terminates it with a four‑step teardown. The handshake steps are:
First handshake: client sends SYN (seq=x) and enters SYN_SEND.
Second handshake: server replies with SYN+ACK (ack=x+1, seq=y) and enters SYN_RECV.
Third handshake: client sends ACK (ack=y+1) and both sides reach ESTABLISHED.
Termination involves four messages (FIN, ACK, FIN, ACK) leading the initiator to TIME_WAIT before moving to CLOSED.
UDP, by contrast, is connectionless and does not perform handshakes, resulting in lower overhead and higher real‑time performance.
TCP vs UDP
TCP is connection‑oriented and provides reliability through handshakes and acknowledgments; UDP is connectionless and unreliable.
Because UDP lacks handshaking, its overhead is smaller and throughput higher, making it suitable for real‑time scenarios despite requiring manual validation if needed.
Common Questions
Maximum concurrent TCP connections : The limit is not the 65,535 port range but the number of file descriptors the OS allows. It can be increased via ulimit -n and kernel parameters.
Why TIME_WAIT lasts 2 MSL : To ensure any lost ACK can be retransmitted; without it, the remote side might miss the final ACK and resend FIN.
Problems caused by many TIME_WAIT sockets : Each TIME_WAIT consumes a local port; heavy short‑connection traffic can exhaust ports, leading to “address already in use” errors. Adjusting kernel parameters such as net.ipv4.tcp_tw_reuse, net.ipv4.tcp_tw_recycle, and net.ipv4.tcp_fin_timeout can mitigate the issue.
Long‑Lived vs Short Connections
Short connections follow connect → data → close. Long connections keep the TCP link open, sending periodic heartbeat packets to maintain the session, allowing multiple data exchanges before closing.
Long connections are preferred when operations are frequent and the number of concurrent sockets is limited, e.g., database connections.
Heartbeat Packets
A heartbeat is a periodic custom command that signals the peer that the socket is still alive. It can be implemented by sending a small predefined message at fixed intervals.
Defining a Custom Application Protocol
To give transmitted data meaning, an application‑layer protocol (e.g., HTTP, MQTT, Dubbo) is needed. The custom protocol design includes:
Heartbeat packet format.
Message header indicating payload length.
Payload serialization format (e.g., JSON).
Example header: length:000000000xxxx where xxxx is the payload length.
Socket Connection Pool
A Socket connection pool maintains a collection of long‑lived sockets, automatically checking their health, discarding invalid ones, and replenishing the pool. Its core attributes are:
Idle socket queue.
Active socket queue.
Waiting request queue.
Invalid socket removal.
Pool size configuration.
Socket creation logic.
When a request arrives, the pool provides an idle socket; if none are available and the active count is below the configured limit, a new socket is created; otherwise the request waits.
Node.js Generic‑Pool Example
The article introduces the generic-pool module. It shows the directory structure, pool initialization, and usage with the previously defined custom protocol. Logs demonstrate that the first two requests create new sockets, while subsequent requests reuse existing sockets from the pool.
Source Code Analysis
The core implementation resides in lib/Pool.js. The constructor defines the idle, active, and waiting queues. The acquire method contains the logic that traverses these queues to finally return a long‑lived socket resource.
Further code details can be examined by reviewing the images of the source files.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect's Guide
Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
