A backend service cannot send bytes directly to "the Internet." It needs a controlled way to ask the operating system to communicate on its behalf.
That interface is a socket.
When an application connects to a database, listens for HTTP requests, sends a DNS query, or streams events to another service, it normally does so through a socket. The application reads and writes data using a programming interface, while the operating system handles transport headers, packet transmission, routing decisions, retransmission when the chosen protocol provides it, and delivery to the correct process.
A socket is therefore the boundary between application code and the operating system's networking stack. Understanding that boundary makes network APIs much less mysterious.
A network socket is an operating-system-managed communication endpoint that an application uses to send or receive data.
The word endpoint matters. A socket is not the wire, the network, or the data itself. It is one end of a communication path.
The application sees operations such as:
The operating system maintains the state behind those operations. Depending on the kind of socket, that state can include local and remote addresses, protocol state, pending errors, and send and receive buffers.
On Unix-like systems, an application usually refers to a socket through a file descriptor, which is a small non-negative integer meaningful inside that process. Windows uses a socket handle. Languages commonly wrap the descriptor or handle in an object such as Python's socket or Java's Socket.
The language object is not the network connection itself. It is the application's reference to networking state managed by the operating system.
Creating a socket requires enough information for the operating system to choose the kind of communication the application wants. Socket APIs express this with three related choices.
The address family defines the form of addresses used by the socket.
Common network families are:
AF_INET for IPv4 addressesAF_INET6 for IPv6 addressesFor example, an IPv4 socket might use 192.0.2.10, while an IPv6 socket might use 2001:db8::10.
Some systems also support local sockets, often called Unix domain sockets, for communication between processes on the same machine. Those are useful IPC mechanisms, but this course chapter focuses on Internet sockets using IPv4 or IPv6.
The socket type defines how data is presented to the application.
The two types used most often are:
SOCK_STREAM, which presents an ordered stream of bytesSOCK_DGRAM, which presents individual datagramsA stream has no built-in application message boundaries. A datagram retains the boundary of each delivered message.
The protocol defines the transport rules used by the socket. For Internet sockets, the common pairings are:
Socket APIs often allow the protocol argument to be 0, meaning "select the normal protocol for this family and type." The type and protocol are related, but they are not the same concept: the type describes the application's data interface, while the protocol defines behavior on the network.
In Python, creating these two kinds of sockets looks like this:
These calls create local socket resources. They do not, by themselves, connect to a remote application or send any data.
Java exposes the same underlying ideas through more specialized classes. Socket represents a TCP client or established TCP endpoint, ServerSocket represents a TCP listener, and DatagramSocket represents a UDP endpoint. The API shape is different, but the operating-system concepts are the same.
For Internet communication, an application normally works with a socket address containing:
An IP address identifies a network interface or host location. A port number helps the operating system select the intended application endpoint on that host.
For example:
means IPv4 address 198.51.100.20, port 8080.
IPv6 addresses contain colons, so a port is conventionally written outside brackets:
Port numbers are 16-bit unsigned values, so their numerical range is 0 through 65535. Port 0 has a special role in socket APIs: binding to it normally asks the operating system to choose an available local port. Applications communicate using the assigned nonzero port.
The transport protocol is also part of the endpoint's meaning. TCP port 8080 and UDP port 8080 belong to separate transport namespaces. A process listening on TCP port 8080 does not automatically receive UDP datagrams sent to port 8080.
Ports and sockets are closely related, but they are not interchangeable.
A port number is one addressing value used for transport-layer delivery. A socket is a live operating-system object owned by a process and configured for a particular kind of communication.
Consider a web server listening on TCP port 8080. Port 8080 is just a number. The server has a socket bound to a local address that includes that number. If the process closes the socket, the number still exists as part of the TCP address space, but that server no longer owns the endpoint.
One process can also own many sockets involving the same server port. A busy service might have:
All four sockets can involve local port 8080, yet they have different roles and state.
A TCP connection is identified conceptually by four values:
The transport protocol is understood to be TCP. The same four numerical values used with UDP would refer to a different protocol context.
Suppose two clients connect to the same API server:
Both clients happen to use source port 53000, and both contact server port 8080. The connections remain distinct because their source IP addresses differ.
The same client can also open several connections to the same server:
Here, the client ports distinguish the connections. Client operating systems normally choose temporary ephemeral ports for outgoing connections unless the application explicitly binds a local port.
This is how thousands of clients can use the same server port at once. The server is not limited to one connection merely because it exposes one well-known endpoint.
Loading simulation...
To receive traffic at a predictable address, a server uses binding. Binding associates a socket with a local IP address and port under the operating system's rules.
A server can commonly bind to one of three kinds of local address:
A specific interface address
The socket receives matching traffic addressed to that local interface.
The loopback address
The service is reachable only through the local IPv4 loopback path. This is useful for a database, development server, or internal helper that should not accept connections from other machines.
The wildcard address
The socket accepts matching IPv4 traffic on the machine's eligible local interfaces. The IPv6 wildcard address is ::.
0.0.0.0 is a local binding instruction, not an address a client should normally use as the destination of a connection. A client needs a specific reachable destination such as 127.0.0.1, a host interface address, or an address obtained from name resolution.
A client often does not call bind() explicitly. When it starts communicating, the operating system chooses an appropriate local IP address and ephemeral port. The client still has a local endpoint; its allocation was simply automatic.
A TCP server does not use one socket object for every purpose.
It first creates a socket, binds it to a local address, and marks it as a listening socket. The listening socket represents the public entry point where connection requests arrive.
When a client connection is ready for the application, the server accepts it. The accept operation returns a new connected socket dedicated to that client. The original listening socket remains available for more clients.
After both clients are accepted, the server conceptually has three socket resources:
The server sends and receives application data through the connected sockets, not through the listener. Closing connection A does not close connection B or the listening socket.
This distinction explains why a server can stop accepting new connections while allowing existing requests to finish: it can close the listener while keeping already accepted sockets open.
The terms client and server describe how applications begin an interaction:
They do not imply that data flows in only one direction. An established TCP socket is normally full-duplex: both applications can send and receive bytes over the same connection.
The labels also do not permanently describe machines. A backend process may act as a server when receiving requests from a mobile app and as a client when connecting to a database. Its role depends on the particular interaction.
At the socket level, both ends ultimately own local socket resources. The asymmetry is mainly in setup: one side listens and accepts, while the other initiates the connection.
A TCP stream socket gives the application an ordered sequence of bytes.
Suppose a sender makes two calls:
The receiver observes the ordered stream:
Its receive calls might return:
or:
or even:
All of these are valid. A successful send does not create a matching receive-sized message on the other side. The application protocol must define how to separate the byte stream into meaningful units, perhaps with delimiters, fixed sizes, or length prefixes.
This is a property of stream sockets, not a bug in the API.
A UDP datagram socket works differently. Each send creates one datagram, and each delivered datagram retains its boundary.
If an application sends:
the receiver does not get one merged "HELLOWORLD" datagram. It receives separate messages if they arrive.
UDP does not require a listening socket or an accept operation. A server usually binds one datagram socket and receives messages from many remote addresses through it. Each receive operation can report which peer sent that datagram, allowing the application to reply to the appropriate address.
An application can ask the operating system to associate a UDP socket with a default peer, often called "connecting" the UDP socket. That makes sending and filtering more convenient, but it does not create a TCP-style transport connection or add reliable delivery.
Applications usually run in user space, while the networking stack and socket state live in the operating-system kernel. A send operation crosses that boundary.
For a typical socket send:
The exact copying and buffering strategy depends on the operating system, protocol, hardware, and API. The important contract is that a normal send call hands data to the local operating system.
A successful send does not prove that:
If a client needs to know that a server stored an order, it needs an application-level response expressing that fact. Transport delivery and business completion are different guarantees.
Network events do not necessarily happen when application code is ready for them. A server may call accept() before any client has connected, or call a receive operation before data has arrived.
In the simplest socket model, such an operation blocks:
Blocking is not the same as wasting CPU in a loop. The operating system can put the waiting thread to sleep and run other work. When the socket's state changes, the operating system wakes the thread.
Socket APIs also support timeouts and models in which calls return immediately when progress is not possible. Those choices affect how an application manages concurrency, but they do not change the basic socket abstraction: the application still operates on an OS-managed endpoint.
Creating a socket consumes operating-system resources. These can include:
A socket should be closed when the application no longer needs it. Closing releases that process's reference and allows the operating system to reclaim the underlying state when no references remain.
Python commonly uses a context manager to make that lifetime explicit:
Java sockets implement AutoCloseable, so try-with-resources serves the same purpose:
The Java example binds a TCP listener to an automatically selected local port and then closes it. Neither example communicates with another process; each only demonstrates explicit resource lifetime.
Failing to close sockets creates a socket leak. A long-running service that continually opens sockets without releasing them can eventually exhaust its descriptor limit or other networking resources, after which new files and connections may fail even if the machine still has CPU and memory available.
The core socket operations form a small vocabulary. The sequences below are conceptual; language libraries may combine steps or use different method names.
A TCP server follows this shape:
A TCP client follows this shape:
A UDP server commonly follows this shape:
A UDP client can usually let the operating system assign its local endpoint and send directly to a destination:
These operations reveal the essential difference between transport models. TCP creates per-connection state and gives a server a new socket for each accepted peer. UDP can exchange independent datagrams with many peers through one bound socket.
Loading simulation...
Suppose an API server should accept connections at 198.51.100.20:8080, and a client runs at 192.0.2.10.
The server:
198.51.100.20:8080.The client:
198.51.100.20:8080.192.0.2.10:53124.The server accepts the ready connection and receives a new connected socket. The resulting endpoints are:
They describe the same connection from opposite ends.
The listener never becomes the client-specific data channel. It remains the entry point. The accepted socket carries the conversation with this client, and another client produces another accepted socket.
A socket is not an IP address. The address is configuration attached to a socket. A machine can have several IP addresses and thousands of sockets.
A socket is not a port. A port is one component used to address transport traffic. A socket is a live OS resource with behavior and state.
A socket is not always a connection. A TCP listener is a socket but not one established client connection. A UDP socket can send and receive without a TCP-style connection at all.
A TCP server does not use only one socket. It normally has one listener plus one connected socket for every accepted client.
Creating a socket does not contact the network. It allocates or prepares a local communication object. Communication begins through later operations.
A successful send does not mean the remote application processed the data. It usually means the local operating system accepted data for the socket.
One send does not imply one receive on a stream socket. TCP preserves byte order, not application write boundaries.
Clients also have ports. The operating system normally selects an ephemeral local port when the client initiates communication.
0.0.0.0 does not mean localhost. As a bind address, it means eligible local IPv4 interfaces. 127.0.0.1 is the IPv4 loopback address.
Client and server do not mean sender and receiver. Once a TCP connection exists, both ends can normally send and receive.
A socket is an operating-system-managed communication endpoint defined by an address family, socket type, and transport protocol. Its socket address contains an IP address and port, but neither value is itself a socket. A TCP connection is identified by both endpoints' IP addresses and ports.
A TCP server retains its listening socket and receives a separate connected socket for each accepted client. TCP sockets carry ordered bytes without preserving send boundaries, while UDP sockets preserve datagrams. A successful send transfers data to the local network stack, not necessarily the remote application.
Sockets consume finite process and kernel resources and must be closed reliably.
Applications operate on local sockets; the operating system uses their hidden state to communicate with remote endpoints.
5 quizzes