We are moving down the checklist of setting up a server.
socket(): Install the telephone (Done).bind(): Assign a phone number so people can call you.
In technical terms, bind assigns a local protocol address to a socket. For TCP/IP, this “address” is the combination of an IP address and a Port number.
1. The Core Logic: bind()
The kernel needs to know which local IP address and which local port your application wants to use to receive data.
Function Prototype:
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);Returns:
- Success:
0. - Error:
-1(setserrno).
2. Breakdown of Arguments
sockfd: The socket descriptor (fromsocket()).myaddr: A pointer to the protocol-specific address structure (e.g.,struct sockaddr_in). This contains the IP and Port you want to assign to this socket.addrlen: The size of that structure.
3. Server vs. Client Usage
This is a key distinction in the book:
- Servers: MUST use bind. Servers need to register a “Well-Known Port” (like port 80 for Web Servers) so clients know where to send connection requests. If a server doesn’t bind a specific port, the kernel will assign a random ephemeral port, and no one will know how to reach it.
- Clients: USUALLY DO NOT use bind. Clients typically don’t care which local port they use; they only care about reaching the server’s port. If a client skips bind, the kernel automatically assigns a local IP and an ephemeral port when the client calls connect.
4. Choosing Your Address (The “Wildcard”)
When a server binds, it has choices regarding the IP address it binds to. A server machine might have multiple network interfaces (e.g., Wi-Fi, Ethernet, localhost).
- Specific IP: If you bind to a specific IP (e.g.,
192.168.1.50), the socket will only accept connections arriving on that specific network card. - Wildcard IP (
INADDR_ANY): This tells the kernel: “I don’t care which network interface the connection comes in on; if it reaches this machine on the specified port, send it to me.” This is the most common setting for general servers.
Summary of Combinations (Based on text):
| IP Address Argument | Port Argument | Result |
|---|---|---|
| Wildcard | 0 | Kernel chooses IP and Port (Rare for servers). |
| Wildcard | Non-zero | Kernel chooses IP; Process specifies Port (Standard for Servers). |
| Specific IP | 0 | Process specifies IP; Kernel chooses Port. |
| Specific IP | Non-zero | Process specifies both (Security/Multi-homing). |
5. Common Errors: EADDRINUSE
The most common error you will encounter with bind is EADDRINUSE (“Address already in use”).
- Scenario: You start your server, it crashes or you stop it (Ctrl+C), and you try to restart it immediately.
- Result:
bindreturns -1 anderrnoisEADDRINUSE. - Why? The OS keeps the port “reserved” for a short time (the
TIME_WAITstate) to clean up leftover packets from the previous connection. - The Fix: The text introduces a socket option called
SO_REUSEADDRin Chapter 7 that tells the kernel to allow you to reuse the port immediately.
6. Code Example
Here is how a standard TCP server binds to the wildcard address and a specific port (e.g., 9877).
struct sockaddr_in servaddr;
// 1. Clear struct
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
// 2. Set the Address (INADDR_ANY = Wildcard / All Interfaces)
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
// 3. Set the Port (htons converts to network byte order)
servaddr.sin_port = htons(9877);
// 4. Call bind
if (bind(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
// Check for EADDRINUSE here!
perror("bind error");
exit(1);
}