SrcForge

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 TypeProtocolReliableConnection
Stream SocketTCPYesConnection-oriented
Datagram SocketUDPNoConnectionless
Raw SocketCustomDependsLow-level networking

TCP vs UDP

FeatureTCPUDP
ReliableYesNo
Ordered DeliveryYesNo
Error CheckingYesLimited
SpeedSlowerFaster
Connection RequiredYesNo
ExampleHTTP, FTP, SSHDNS, Video Streaming, Online Gaming

Important Socket Functions

FunctionPurpose
`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

WrongCorrect
Ignoring return values of socket functionsCheck every system call for errors
Forgetting to call bind() before listen()Always bind first
Forgetting to close socketsCall close() after communication
Using fixed-size buffers without validationValidate received data and buffer sizes
Assuming send() or recv() transfers all data in one callLoop 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.

Prev: IPC and SignalsBack to hub