CLOSE
Updated on 17 Jun, 202519 mins read 9 views

In this article, you’ll create a Full-Duplex TCP Echo Server and Client. This means the client and server can send and receive data independently and simultaneously—just like in real-world chat systems.

🎯 Objective

Build a server that:

  • Accepts multiple messages from the client.
  • Echoes each message back.

And a client that:

  • Sends multiple messages to the server.
  • Receives the echo responses.
  • Can send and receive concurrently (optional enhancement).

⚙️ Part 1: Echo Server (Single-Client, Full-Duplex)

Step-by-Step Breakdown

  1. Create the socket
  2. Bind to IP and port
  3. Listen and accept a connection
  4. Enter a loop:
    1. Read from client
    2. Print and echo back
    3. Break if client sends "exit"

Full Code: echo_server.c

#include <stdio.h>              // For printf(), perror()
#include <stdlib.h>             // For exit()
#include <string.h>             // For memset(), strncmp(), strlen()
#include <unistd.h>             // For close(), read(), write()
#include <arpa/inet.h>          // For inet_ntoa(), htons(), etc.
#include <netinet/in.h>         // For sockaddr_in structure
#include <sys/socket.h>         // For socket system calls

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

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

    // 2. Configure server address structure
    server_addr.sin_family = AF_INET;              // IPv4
    server_addr.sin_port = htons(8080);            // Port 8080 (network byte order)
    server_addr.sin_addr.s_addr = INADDR_ANY;      // Listen on all available interfaces

    // 3. Bind the socket to the address and port
    bind(server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));

    // 4. Start listening for incoming connections (max 5 in queue)
    listen(server_fd, 5);

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

    // 5. Accept a client connection
    client_fd = accept(server_fd, (struct sockaddr*)&client_addr, &addrlen);
    printf("Client connected: %s:%d\n",
           inet_ntoa(client_addr.sin_addr),       // Convert IP to readable format
           ntohs(client_addr.sin_port));          // Convert port to host byte order

    // 6. Communication loop
    while (1) {
        memset(buffer, 0, sizeof(buffer));         // Clear buffer before each read
        int bytes = read(client_fd, buffer, sizeof(buffer));  // Read from client
        if (bytes <= 0) break;                     // Exit loop on error or disconnect

        printf("Client: %s", buffer);              // Print client message

        if (strncmp(buffer, "exit", 4) == 0) break; // If message starts with "exit", break

        send(client_fd, buffer, strlen(buffer), 0); // Echo message back to client
    }

    // 7. Close client and server sockets
    close(client_fd);
    close(server_fd);
    printf("Connection closed.\n");

    return 0;
}

What this program does:

  • Listens on TCP port 8080.
  • Accepts a single client.
  • Echoes back any message received.
  • Terminates when it receives "exit" from the client.

⚙️ Part 2: Echo Client (Interactive)

Full Code: echo_client.c

#include <stdio.h>              // For printf(), fgets(), etc.
#include <stdlib.h>             // For exit()
#include <string.h>             // For memset(), strlen(), strncmp()
#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 system calls

int main() {
    int sock_fd;
    struct sockaddr_in server_addr;
    char buffer[1024];          // Buffer for sending and receiving data

    // 1. Create TCP socket
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);

    // 2. Setup server address
    server_addr.sin_family = AF_INET;              // IPv4
    server_addr.sin_port = htons(8080);            // Port 8080 in network byte order
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr); // Convert IP to binary format

    // 3. Connect to the server
    connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));

    printf("Connected to server. Type messages (type 'exit' to quit):\n");

    // 4. Communication loop
    while (1) {
        memset(buffer, 0, sizeof(buffer));          // Clear the buffer before input
        fgets(buffer, sizeof(buffer), stdin);       // Get user input (includes newline)
        send(sock_fd, buffer, strlen(buffer), 0);   // Send message to server

        if (strncmp(buffer, "exit", 4) == 0) break;  // If input starts with "exit", exit loop

        memset(buffer, 0, sizeof(buffer));          // Clear buffer for server response
        read(sock_fd, buffer, sizeof(buffer));      // Read server response
        printf("Server: %s", buffer);               // Print server response
    }

    // 5. Close the socket
    close(sock_fd);
    return 0;
}

What it does:

  • Connects to a TCP server at 127.0.0.1:8080
  • Accepts user input using fgets()
  • Sends input to the server and prints the response
  • Quits the loop when the input starts with "exit"

Demo

1 Compile both programs:

gcc echo_server.c -o server
gcc echo_client.c -o client

2 Run server in one terminal:

./server

3 Run client in another

./client