In this chapter, we delve into the core C/C++ system calls and functions that power socket programming. These are the building blocks that allow us to send and receive data over a network.
Every networking program in C/C++—whether it’s a web server, a chat client, or a file transfer application—relies heavily on these key socket APIs.
Flow of Socket Program
Before going deeper, here's the overall flow of a typical socket program.
For Server:
socket() → bind() → listen() → accept() → recv()/send() → close()
For Client:
socket() → connect() → send()/recv() → close()
1️⃣ Socket()
Purpose:
Creates a socket, which is an endpoint for communication.
Syntax:
int socket(int domain, int type, int protocol);
Parameters:
- domain: Address family (usually
AF_INET
for IPv4 orAF_INET6
for IPv6) - type: Type of socket (e.g.,
SOCK_STREAM
for TCP,SOCK_DGRAM
for UDP( - protocol: Usually set to 0 (auto-select)
Example:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
📍 2️⃣ bind()
Purpose:
Associates the socket with a local IP address and port number.
Syntax:
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Parameters:
- sockfd: Socket file descriptor
- addr: Pointer to a a
sockaddr_in
structure (cast to sockaddr*) - addrlen: Size of
addr
structure
Example:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080); // Port 8080
server_addr.sin_addr.s_addr = INADDR_ANY; // Any local IP
bind(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
📡 3️⃣ listen()
Purpose:
Marks a socket as passive, ready to accept incoming connection (TCP only).
Syntax:
int listen(int sockfd, int backlog);
Parameters:
- sockfd: Socket file descriptor
- backlog: Maximum number of pending connections
Example:
listen(sockfd, 5); // Queue up to 5 pending connections
🤝 4️⃣ accept()
Purpose:
Accepts a new incoming connection request.
Syntax:
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
Parameters:
- sockfd: The listening socket
- addr: Populated with client's address
- addrlen: Pointer to length of the address structure
Example:
struct sockaddr_in client_addr;
socklen_t len = sizeof(client_addr);
int client_sock = accept(sockfd, (struct sockaddr*)&client_addr, &len);
if (client_sock < 0) {
perror("accept failed");
exit(EXIT_FAILURE);
}
🔗 5️⃣ connect() (client side)
Purpose:
Initiates a connection to a remote server (used on the client side).
Syntax:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Example:
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);
connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
📤 6️⃣ send() and recv()
send()
Sends data on connected socket (TCP).
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
recv()
Received data from a connected socket.
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
Example:
char buffer[1024];
send(client_sock, "Hello from server", 17, 0);
recv(client_sock, buffer, sizeof(buffer), 0);
7️⃣ sendto() and recvfrom() (for UDP)
used with connectionless protocols like UDP.
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
🧹 8️⃣ close()
Purpose:
Closes the socket file descriptor.
Example:
close(sockfd);
Error Handling
Most socket functions return -1
on error and set the global errno
. Always check return values and use perror()
or strerror()
for debugging.
if (connect(sockfd, ...) < 0) {
perror("Connection failed");
exit(EXIT_FAILURE);
}