CLOSE

TCP (Transmission Control Protocol) is one of the most reliable ways to communicate over a network. In this guide, we will walk through how to build a basic TCP server in C/C++ using socket programming.

What is a TCP Server?

A TCP server is a program that:

  1. Waits (listens) for incoming connections from clients.
  2. Accepts a connection request.
  3. Reads data sent by the client.
  4. Sends responses (optional)
  5. Closes the connection gracefully.

Required Headers

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>         // close()
#include <arpa/inet.h>      // inet_ntoa(), htons(), etc.
#include <netinet/in.h>     // sockaddr_in
#include <sys/socket.h>     // socket(), bind(), listen(), accept()

Step-by-Step: Building a TCP Server

1️⃣ Create a Socket

int server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd == -1) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
}
  • AF_INET – IPv4 address family
  • SOCK_STREAM – TCP (as opposed to SOCK_DGRAM for UDP)
  • 0 – default protocol (TCP in this case)

2️⃣ Set Up Server Address Structure

struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);              // Port number (8080)
server_addr.sin_addr.s_addr = INADDR_ANY;        // Bind to all interfaces
  • htons() – converts port from host to network byte order
  • INADDR_ANY – binds to all available network interfaces

3️⃣ Bind the Socket to the IP/Port

if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
    perror("Bind failed");
    exit(EXIT_FAILURE);
}

This reserves the specified port so the server can listen on it

4️⃣ Listen for incoming Connections

if (listen(server_fd, 5) < 0) {
    perror("Listen failed");
    exit(EXIT_FAILURE);
}
  • The 5 is the backlog: how many connections can be queued before being accepted.

5️⃣ Accept Client Connections

struct sockaddr_in client_addr;
socklen_t addrlen = sizeof(client_addr);

int client_socket = accept(server_fd, (struct sockaddr *)&client_addr, &addrlen);
if (client_socket < 0) {
    perror("Accept failed");
    exit(EXIT_FAILURE);
}

printf("Connection accepted from %s:%d\n",
       inet_ntoa(client_addr.sin_addr),
       ntohs(client_addr.sin_port));

6️⃣ Communicate with the Client

char buffer[1024] = {0};
read(client_socket, buffer, sizeof(buffer));
printf("Client: %s\n", buffer);

char *response = "Hello from server!";
send(client_socket, response, strlen(response), 0);

7️⃣ Close Sockets

close(client_socket);
close(server_fd);

Full Working Code of the Server:

#include <stdio.h>              // Standard I/O functions
#include <stdlib.h>             // For exit()
#include <string.h>             // For memset and string operations
#include <unistd.h>             // For close()
#include <arpa/inet.h>          // For inet_ntoa, htons, etc.
#include <netinet/in.h>         // For sockaddr_in
#include <sys/socket.h>         // For socket functions

int main() {
    int server_fd, client_socket;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addrlen = sizeof(client_addr);
    char buffer[1024] = {0};

    // 1. Create a TCP socket (IPv4, stream-based)
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("Socket failed");
        exit(EXIT_FAILURE);
    }

    // 2. Set server address structure
    server_addr.sin_family = AF_INET;           // IPv4
    server_addr.sin_port = htons(8080);         // Port 8080 (converted to network byte order)
    server_addr.sin_addr.s_addr = INADDR_ANY;   // Bind to any available interface (localhost or network)

    // 3. Bind the socket to the specified IP and port
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Bind failed");
        exit(EXIT_FAILURE);
    }

    // 4. Listen for incoming connections (maximum 5 queued connections)
    if (listen(server_fd, 5) < 0) {
        perror("Listen failed");
        exit(EXIT_FAILURE);
    }

    printf("Server is listening on port 8080...\n");

    // 5. Accept a new client connection
    client_socket = accept(server_fd, (struct sockaddr *)&client_addr, &addrlen);
    if (client_socket < 0) {
        perror("Accept failed");
        exit(EXIT_FAILURE);
    }

    // 6. Print client's IP and port
    printf("Connection accepted from %s:%d\n",
           inet_ntoa(client_addr.sin_addr),       // Convert client's IP to human-readable string
           ntohs(client_addr.sin_port));          // Convert client's port to host byte order

    // 7. Receive data from the client
    read(client_socket, buffer, sizeof(buffer));
    printf("Client says: %s\n", buffer);

    // 8. Send a response to the client
    char *msg = "Hello from server!";
    send(client_socket, msg, strlen(msg), 0);

    // 9. Close both client and server sockets
    close(client_socket);
    close(server_fd);

    return 0;
}

This code sets up a simple TCP server that listens on port 8080, accepts one client connection, receives a message, sends a response, and then exits.

What is a TCP Client?

A TCP client is a program that:

  1. Creates a socket.
  2. Connects to a server's IP address and port.
  3. Sends a request or data.
  4. Receives a response from the server.
  5. Closes the connection.

Step-by-Step: Writing a TCP Client

Required Headers

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>         // close()
#include <arpa/inet.h>      // inet_pton(), sockaddr_in
#include <netinet/in.h>     // struct sockaddr_in
#include <sys/socket.h>     // socket(), connect()

1️⃣ Create a Socket

int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd < 0) {
    perror("Socket creation failed");
    exit(EXIT_FAILURE);
}

Same as the server – we use AF_INET and SOCK_STREAM.

2️⃣ Setup Server Address Structure

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);  // Convert IP to binary form
  • inet_pton() – converts a human-readable IP to network format.

3️⃣ Connect to Server

if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
    perror("Connection failed");
    exit(EXIT_FAILURE);
}
  • The TCP client initiates the connection to the server.

4️⃣ Send a Message to the Server

char *msg = "Hello from client!";
send(sock_fd, msg, strlen(msg), 0);

5️⃣ Receives Response

char buffer[1024] = {0};
read(sock_fd, buffer, sizeof(buffer));
printf("Server replied: %s\n", buffer);

6️⃣ Close the Connection

close(sock_fd);

Full Working Client Code:

#include <stdio.h>              // Standard I/O functions
#include <stdlib.h>             // For exit()
#include <string.h>             // For memset and string operations
#include <unistd.h>             // For close(), read(), write()
#include <arpa/inet.h>          // For inet_pton(), htons(), etc.
#include <netinet/in.h>         // For sockaddr_in
#include <sys/socket.h>         // For socket functions

int main() {
    int sock_fd;
    struct sockaddr_in server_addr;
    char buffer[1024] = {0};    // Buffer to store incoming message from server

    // 1. Create a socket (IPv4, TCP)
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_fd < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 2. Set up the server address structure
    server_addr.sin_family = AF_INET;            // IPv4
    server_addr.sin_port = htons(8080);          // Port 8080 (host to network byte order)

    // 3. Convert and set the IP address (127.0.0.1 => localhost)
    if (inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) <= 0) {
        perror("Invalid address / Address not supported");
        exit(EXIT_FAILURE);
    }

    // 4. Connect to the server
    if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("Connection Failed");
        exit(EXIT_FAILURE);
    }

    // 5. Send a message to the server
    char *msg = "Hello from client!";
    send(sock_fd, msg, strlen(msg), 0);
    printf("Message sent to server.\n");

    // 6. Read response from server
    read(sock_fd, buffer, sizeof(buffer));
    printf("Server response: %s\n", buffer);

    // 7. Close the socket
    close(sock_fd);

    return 0;
}

This client program:

  • Connects to a server running on 127.0.0.1:8080
  • Sends a greeting message
  • Waits for the response from the server
  • Prints the server's response and closes the connection