Lesson 43
Socket Programming
Socket Programming in C is the process of creating applications that communicate over a network using sockets. A socket is an endpoint of communication identified by an IP address, port number, and protocol. The client-server model forms the foundation of socket communication, with TCP providing reliable connection-oriented transfer and UDP offering faster connectionless communication. Core APIs include socket(), bind(), listen(), accept(), connect(), send(), recv(), and close().
C Track
Save progress as you learn.
44 lessons
Lesson content
Socket Programming in C: A Complete Beginner to Advanced Guide
What is Socket Programming in C?
Modern applications rarely work in isolation. Web browsers communicate with web servers, chat applications exchange messages in real time, and online games connect players across the globe. This communication is made possible through socket programming.
Socket Programming in C is the process of creating applications that communicate over a network using sockets. A socket is an endpoint of communication between two devices, allowing them to send and receive data.
Think of a socket as a telephone connection. One person dials a number (client), another answers the call (server), and both exchange information over the connection.
Why Does Socket Programming Exist?
Without sockets, computers could not communicate over networks, client-server applications would not exist, and internet services such as websites, email, and file transfers would be impossible. Socket programming provides reliable communication between applications, data exchange over local and remote networks, and real-time communication for distributed systems.
Real-World Use Cases
Socket programming is widely used in:
- Web servers
- Web browsers
- Chat applications
- Multiplayer games
- Video conferencing
- Email clients
- IoT devices
- Cloud services
- Database servers
- File transfer applications
Prerequisites
Before learning Socket Programming in C, you should understand:
- Basic C programming
- Functions
- Pointers
- Structures
- Arrays
- File descriptors
- Basic Linux commands
- IP addresses and ports
- TCP/IP networking fundamentals
Core Concepts
What is a Socket?
A socket is a software endpoint used for communication between two processes over a network. Every socket is identified by an IP address, a port number, and a protocol (TCP or UDP).
Client and Server Model
Socket communication follows the client-server architecture. The server waits for incoming connections, accepts client requests, processes them, and sends responses. The client initiates the connection, sends requests, and receives responses.
Types of Sockets
| Socket Type | Protocol | Reliable | Connection |
|---|---|---|---|
| Stream Socket | TCP | Yes | Connection-oriented |
| Datagram Socket | UDP | No | Connectionless |
| Raw Socket | Custom | Depends | Low-level networking |
TCP vs UDP
| Feature | TCP | UDP |
|---|---|---|
| Reliable | Yes | No |
| Ordered Delivery | Yes | No |
| Error Checking | Yes | Limited |
| Speed | Slower | Faster |
| Connection Required | Yes | No |
| Example | HTTP, FTP, SSH | DNS, Video Streaming, Online Gaming |
Important Socket Functions
| Function | Purpose |
|---|---|
| `socket()` | Create a socket |
| `bind()` | Assign IP and port |
| `listen()` | Wait for client connections |
| `accept()` | Accept a client connection |
| `connect()` | Connect to a server |
| `send()` | Send data |
| `recv()` | Receive data |
| `close()` | Close a socket |
Socket Programming Workflow
Server workflow: create socket → bind socket → listen for connections → accept client → send and receive data → close socket.
Client workflow: create socket → connect to server → send data → receive response → close socket.
Code Examples
Example 1: Beginner – Creating a Socket
#include <stdio.h> // Standard input/output library
#include <sys/socket.h> // Socket functions
#include <netinet/in.h> // Internet address structures
#include <unistd.h> // close()
int main() // Program entry point
{
int sockfd; // Socket descriptor
sockfd = socket(AF_INET, SOCK_STREAM, 0); // Create TCP socket
if (sockfd < 0) // Check for failure
{
printf("Socket creation failed\n"); // Display error
return 1; // Exit program
}
printf("Socket created successfully\n"); // Success message
close(sockfd); // Close socket
return 0; // Exit successfully
}Example 2: Intermediate – TCP Server
#include <stdio.h> // Standard I/O library
#include <string.h> // String functions
#include <unistd.h> // close()
#include <arpa/inet.h> // Internet functions
int main() // Program entry point
{
int serverSocket; // Server socket descriptor
struct sockaddr_in serverAddr; // Server address structure
serverSocket = socket(AF_INET, SOCK_STREAM, 0); // Create socket
serverAddr.sin_family = AF_INET; // IPv4
serverAddr.sin_port = htons(8080); // Port number
serverAddr.sin_addr.s_addr = INADDR_ANY; // Accept any interface
bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)); // Bind socket
listen(serverSocket, 5); // Listen for connections
printf("Server waiting on port 8080...\n"); // Status message
close(serverSocket); // Close socket
return 0; // Exit program
}Example 3: Intermediate – TCP Client
#include <stdio.h> // Standard I/O library
#include <arpa/inet.h> // Internet functions
#include <unistd.h> // close()
int main() // Program entry point
{
int clientSocket; // Client socket descriptor
struct sockaddr_in serverAddr; // Server address
clientSocket = socket(AF_INET, SOCK_STREAM, 0); // Create socket
serverAddr.sin_family = AF_INET; // IPv4
serverAddr.sin_port = htons(8080); // Port number
inet_pton(AF_INET, "127.0.0.1", &serverAddr.sin_addr); // Localhost
connect(clientSocket,
(struct sockaddr*)&serverAddr,
sizeof(serverAddr)); // Connect to server
printf("Connected to server\n"); // Success message
close(clientSocket); // Close socket
return 0; // Exit program
}Example 4: Advanced – Sending Data
#include <stdio.h> // Standard I/O library
#include <string.h> // String functions
#include <sys/socket.h> // Socket functions
int main() // Program entry point
{
int sockfd = 0; // Assume valid socket
char message[] = "Hello Server"; // Message to send
send(sockfd, // Socket descriptor
message, // Data buffer
strlen(message), // Number of bytes
0); // Default flags
return 0; // Exit program
}Example 5: Advanced – Receiving Data
#include <stdio.h> // Standard I/O library
#include <sys/socket.h> // Socket functions
int main() // Program entry point
{
int sockfd = 0; // Assume valid socket
char buffer[1024]; // Receive buffer
recv(sockfd, // Socket descriptor
buffer, // Buffer
sizeof(buffer), // Maximum bytes
0); // Default flags
printf("%s\n", buffer); // Display received message
return 0; // Exit program
}Common Mistakes and Pitfalls
| Wrong | Correct |
|---|---|
| Ignoring return values of socket functions | Check every system call for errors |
| Forgetting to call bind() before listen() | Always bind first |
| Forgetting to close sockets | Call close() after communication |
| Using fixed-size buffers without validation | Validate received data and buffer sizes |
| Assuming send() or recv() transfers all data in one call | Loop until all required bytes are sent or received |
Wrong:
socket(AF_INET, SOCK_STREAM, 0);
bind(...);
listen(...);Correct:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket");
return 1;
}Best Practices
- Check the return value of every socket API call.
- Use perror() or strerror() for meaningful error messages.
- Close sockets after use to avoid resource leaks.
- Use setsockopt() with SO_REUSEADDR for servers that restart frequently.
- Handle partial sends and receives by looping until all data is transferred.
- Validate all input received from clients.
- Use non-blocking sockets or I/O multiplexing (select(), poll(), or epoll()) for scalable servers.
- Protect network applications against malformed or malicious input.
- Use TLS/SSL for secure communication when transmitting sensitive information.
- Organize networking code into reusable functions or modules.
When NOT to Use This
Socket programming may not be the best choice when:
- Communication is only between processes on the same machine and simpler IPC mechanisms such as pipes or shared memory are sufficient.
- You need high-level communication features provided by frameworks or libraries.
- Rapid application development is more important than low-level network control.
- Your application benefits from protocols such as HTTP, gRPC, or WebSockets that are already implemented by mature libraries.
Summary / Key Takeaways
- Socket programming enables communication between applications over a network.
- A socket is identified by an IP address, port number, and protocol.
- The client initiates communication, while the server waits for connections.
- TCP provides reliable, connection-oriented communication.
- UDP provides faster, connectionless communication with lower overhead.
- Common socket APIs include socket(), bind(), listen(), accept(), connect(), send(), recv(), and close().
- Always check return values and properly close sockets.
- Scalable network applications require careful handling of multiple clients and partial data transfers.
FAQ About Socket Programming in C
1. What is Socket Programming in C?
Socket programming is the process of creating applications that communicate over a network using sockets. It forms the basis of client-server communication.
2. What is the difference between TCP and UDP?
TCP is connection-oriented, reliable, and guarantees ordered delivery. UDP is connectionless, faster, and does not guarantee delivery or ordering.
3. Why do servers call listen() and accept()?
listen() puts a bound socket into a passive state waiting for incoming connections. accept() accepts a pending client connection and returns a new socket dedicated to communicating with that client.
4. Why should I check the return values of socket functions?
Network operations can fail due to invalid addresses, unavailable ports, timeouts, permission issues, or network errors. Checking return values allows your program to detect and handle these situations gracefully.
5. Can one server communicate with multiple clients?
Yes. A server can handle multiple clients by creating a new process or thread for each client, or by using I/O multiplexing techniques such as select(), poll(), or epoll() to manage many connections efficiently.