99% of developers don't get sockets.

What actually is a socket?

You've probably seen electrical sockets, but I'm referring to a completely different kind of socket in the software industry or computer science universe.

Electrical Sockets

Some ideas, such as sockets, anonymous pipes, file descriptors, etc., are just not adequately represented by us. Most developers' conceptions of these ideas end up being vague, wavy creations. Additionally, there are numerous other ideas and phrases that require attention and are not presented in nearly enough detail. I will thus give you a brief overview of sockets and explain what you need to know about them in this post. So, the next time someone asks you these questions, could you tell me what a socket is, how TCP or UDP uses sockets, and which OSI model layer sockets work in? You won't be at a loss for ideas.

It is always best to begin with a specific response to the query, "What are sockets?" Essentially, sockets are an abstraction that operating systems give to allow for communication between several processes on the same machine or over a network. In a two-way communication channel, they serve as endpoints. Therefore, each side of a connection will construct a socket when two machines or two apps need to communicate with one another via the internet or a local network. Additionally, a "socket" is basically a software construct that encapsulates a combination of an IP address, a port number, and a protocol, such as TCP or UDP. This combination is used by the operating system to properly route messages. It can be compared to a telephone.

The IP address and port are like the phone number and extension, while a socket represents the phone. To create a connection, the two sides need to dial each other appropriately. Maybe you've heard of the OSI model, but you're wondering how sockets fit into it. The OSI model, a conceptual framework for network system communication, is where sockets should be placed in order to comprehend them in context.

Socket as phone

In the OSI model, sockets mostly function at the transport layer, often known as layer 4. The socket API is called by the application layer, often known as layer 7, such as your web browser or a back-end service, requesting that it send or receive data. After adding some headers and wrapping the data into TCP or UDP segments, the socket forwards it to the network layer or layer 3, which handles IP routing.

Thus, sockets hide developers from the intricacies of routing, packet fragmentation, retransmission, etc., and offer a clear interface between application logic and the underlying network stack. Alright, but before you can truly comprehend sockets, you must be aware that there are two primary types of sockets: TCP and UDP.

Transmission control protocol sockets, or TCP sockets, are connection-oriented and offer dependable, error-checked, and ordered data transfer. A three-way handshake involving the exchange of SIN and ACT packets is carried out to establish the connection before data is delivered. This ensures that both parties are prepared, and TCP is perfect for applications like file transfers, database access, and web browsing since it guarantees that packets will arrive in the correct order and without duplication.

On the other hand, the user datagram protocol, or UDP, is unreliable and connectionless. Without a handshake, it merely sends datagrams to the target IP and port. Delivery, ordering, and integrity are not guaranteed. But as a result, it's much lighter and faster, which makes it perfect for real-time applications where speed is more important than dependability, like streaming videos.

Sockets have a defined life cycle on the server side. The first step is to create a listening socket that is connected to a particular IP address and port. This socket waits for incoming client connections rather than communicating directly.

A new socket instance is created specifically for the client after the server accepts a connection made by the client, and the existing socket keeps listening for more requests. This new socket serves as the conduit for all correspondence with that particular client. And because of this, a server may manage numerous clients at once, each with its own socket.

Multi-threading or multi-processing, in which every client connection is controlled by a different thread or process, is usually used to handle this in synchronous settings. Although this strategy is simple and effective for a limited number of connections, it is not scalable. Every thread has overhead associated with context switching and memory consumption. Additionally, the performance rapidly deteriorates as the number of concurrent sockets increases because of resource fatigue and contention. Techniques like non-blocking IO or event-driven architectures are used to overcome this issue in high performance systems like message brokers, multiplayer gaming servers, and real-time APIs.

These methods enable the simultaneous management of thousands of open sockets by a single thread or a small group of threads. System functions like select, pull, or even more scalable options like e-pole on Linux or KQ on BSD or Mac OS are used to do this. These methods alert the application only when certain sockets are prepared for reading or writing.

By preventing idle waiting or redundant pulling, these event notification systems significantly lower CPU consumption and latency, which is why they are the cornerstone of frameworks like Engine X, Node.js, and Async.io.

The client establishes a socket and connects to the IP address and port of the server. This starts the three-way handshake if TCP is being used. Like working with a file, the client can write to and read from the socket once it is connected. Sockets can actually be used with standard system calls like read and write since they are regarded as file descriptors on Unix-like platforms. To refresh your memory, a file descriptor is essentially an entry that the operating system creates to represent a file and keep information about it when it is opened. Therefore, there will be ten entries in the kernel for every ten files that are open in your operating system. And these entries are nothing, but simple integers called file descriptions.

In exactly the same way, an integer is also used to represent opening a network socket. The socket descriptor in this instance. In order to free up system resources and stop memory leaks, both the client and the server are expected to shut the socket after the conversation is over. Resource fatigue may result from any incorrectly closed sockets, particularly on servers that are busy. Interesting peculiarities pertaining to socket internals and states are also present. As a result, the system keeps a state machine for every connection to TCP sockets.

LISTEN, SIN-SENT, SIN-RECIEVED, ESTABLISHED, FIN-WAIT-1, TIME-WAIT, and CLOSE-WAIT are a few of the common states. Additionally, these states correspond to different stages of connection setup, upkeep, and disassembly. To prevent delayed packets from an old connection from being mistakenly regarded as belonging to a new one, the TIME-WAIT status, for example, is used. Additionally, understanding these stages is essential for detecting problems that frequently afflict servers or high concurrency applications, such as port exhaustion or socket leakage. However, how does the operating system handle socket uniqueness and port numbers in practice?

A five-tuple consisting of the protocol, source IP, source port, destination IP, and destination port uniquely identifies each socket. Additionally, even when several connections are communicating to the same remote server and port at the same time, this combination enables the OS to discern between them.

For instance, the OS will allocate a distinct source port to each of the browser tabs connected to example.com:443 so that the client and server can distinguish between those sessions. One machine can have hundreds of open connections to various or even identical distant services thanks to this mechanism. However, network communication is the main topic of socket debates.

Unix domain sockets, or UDS, are another significant form, such as TCP or UDP over IP. Network sockets are not what these are. On the same host, they are employed for inter-process communication, or IPC. Thus, UDS employs a file path on the file system in place of an IP address and port. For instance, the address might be /temp/app.sock. Since they completely avoid the network stack and don't require any IP routing or protocol overhead, they are significantly faster than network sockets.

When efficiency and security are crucial, UDS is frequently used by default for local client-server communication in programs like Postgres SQL and Redis, which you are most likely already familiar with. However, it's crucial to remember that sockets are by nature unsafe. And the reason for this is that, unless specifically encrypted, they send raw data. TLS, or transport layer security, is typically used to provide secure socket connection. An existing socket connection is wrapped with TLS, which guarantees that any data transmitted over it is encrypted and verified. For instance, the SSL module in Python offers the ability to encapsulate a plain socket in TLS. For apps that send sensitive data, such as passwords, financial transactions, private user information, etc., this is crucial.

Man-in-the-middle attacks and packet sniffing can target any unconfigured or raw sockets that do not employ TLS. There is socket-based connectivity everywhere. Popular protocols for service-to-service communication include gRPC over HTTP2, which is likewise TCP based, and restful APIs over HTTP, which employ TCP sockets. Socket level routing and traffic shaping are controlled by service meshes like ISTTO and load balancers like EngineX or Envoy. For ultra-low latency communication, engineers occasionally construct proprietary binary protocols over raw TCP or UDP connections in high performance systems. Sockets behind the hood are used by technologies such as CFKA, Redis, and Cassandra to distribute data among nodes.

You should at least be able to explain what a socket is for a very good reason. In actuality, sockets constitute the cornerstone of contemporary work computers. Sockets are used to communicate data across the wire whenever you send an email, stream a video, view a web page, or use a mobile application.

Gaining a thorough understanding of socket operation as a developer allows you to manage the security and performance of network connection. It also lets you optimize communication protocols, solve complicated problems, and create scalable back-end systems. You will be much more successful if you have a firm understanding of sockets. if this article taught you something new. Post a remark and a like.

Keep learning and keep growing.