0Pricing
C Academy · Lesson

TCP Server

Accept connections.

TCP Server is a free C Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Building a TCP Server

A TCP server waits for clients and accepts their connections. The lifecycle is: create a socket, bind it to a port, listen, then accept connections in a loop.

Step 1: Create the Socket

Create a stream socket for IPv4 TCP. A negative result means failure.

#include <sys/socket.h>
#include <stdio.h>

int make_server_socket(void) {
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) { perror("socket"); }
    return fd;
}

Step 2: Allow Address Reuse

By default a port lingers in TIME_WAIT after the server stops, blocking restarts. Set SO_REUSEADDR with setsockopt so you can rebind immediately.

#include <sys/socket.h>

void allow_reuse(int fd) {
    int yes = 1;
    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);
}

Step 3: Bind to a Port

bind() attaches the socket to a local address and port. INADDR_ANY listens on all network interfaces.

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int bind_port(int fd, unsigned short port) {
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(port);
    if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
        perror("bind"); return -1;
    }
    return 0;
}

Step 4: Listen

listen() marks the socket as passive (ready to accept). The backlog argument sets how many pending connections the kernel may queue.

#include <sys/socket.h>
#include <stdio.h>

int start_listen(int fd) {
    if (listen(fd, 16) < 0) { /* backlog of 16 */
        perror("listen"); return -1;
    }
    return 0;
}

Step 5: Accept Connections

accept() blocks until a client connects, then returns a new socket for that client. The original socket keeps listening.

#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

int accept_one(int listen_fd) {
    struct sockaddr_in cli;
    socklen_t len = sizeof cli;
    int conn = accept(listen_fd, (struct sockaddr *)&cli, &len);
    if (conn < 0) perror("accept");
    return conn;
}

Two Sockets, Two Roles

After accept you have two sockets:

  • The listening socket keeps accepting new clients
  • The connection socket talks to one specific client

Close the connection socket when done with that client.

Reading the Request

Use recv to read client data into a buffer. A return of 0 means the client disconnected; -1 means an error.

#include <sys/socket.h>
#include <stdio.h>

void handle(int conn) {
    char buf[256];
    ssize_t n = recv(conn, buf, sizeof buf - 1, 0);
    if (n > 0) { buf[n] = 0; printf("got: %s\n", buf); }
}

Sending a Response

Reply with send. For large data, loop until all bytes are sent, since a single call may write only part of the buffer.

#include <sys/socket.h>
#include <string.h>

void reply(int conn) {
    const char *msg = "hello from server\n";
    size_t left = strlen(msg);
    const char *p = msg;
    while (left > 0) {
        ssize_t n = send(conn, p, left, 0);
        if (n <= 0) break;
        p += n; left -= (size_t)n;
    }
}

The Accept Loop

A simple iterative server accepts one client, serves it, closes it, then loops back to accept the next. It handles clients one at a time.

#include <unistd.h>

void serve_loop(int listen_fd, int (*accept_one)(int), void (*handle)(int)) {
    for (;;) {
        int conn = accept_one(listen_fd);
        if (conn < 0) continue;
        handle(conn);
        close(conn); /* done with this client */
    }
}

Graceful Shutdown

Close the listening socket when the server stops, and handle SIGINT to break the loop cleanly. Always close descriptors to release kernel resources.

Quick Check

Test your understanding of TCP servers.

Recap

You built a TCP server step by step.

  • socket, then SO_REUSEADDR, then bind, listen, accept
  • accept returns a new per-client socket
  • recv/send to communicate, then close the connection
  • Loop to serve clients; check every return value

Frequently asked questions

Is the “TCP Server” lesson free?

Yes — the full text of “TCP Server” is free to read here on the web, and the C Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO.

What will I learn in “TCP Server”?

Accept connections. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C Academy?

No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “TCP Server” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C Academy lesson?

Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Sockets Overview
  2. TCP Server
  3. TCP Client
  4. Handling Multiple Clients
← Back to C Academy