The Ultimate Guide to TCP Client-Server Programming in C [Code]

TCP client-server programming in C is a critical skill for systems developers, backend engineers, and anyone dealing with low-level networking. It’s the foundation of everything from chat servers and IoT systems to custom network daemons.

This guide will take you from basic theory to a multithreaded TCP server, explaining every step in between.

What is TCP Client-Server Programming?

In TCP client-server architecture, one program (server) waits for connections, and others (clients) initiate communication.

  • TCP ensures reliable, ordered delivery of data.
  • Server runs continuously, listens on a port.
  • Client connects to the server, sends and receives data.

This is connection-oriented programming—both sides perform a “handshake” to establish a session.

TCP 3-way handshake
TCP 3-way handshake

Understanding TCP/IP and Sockets

Before writing code, let’s understand what happens under the hood.

LayerProtocolPurpose
ApplicationHTTP, FTP, CustomYou write this!
TransportTCPReliable byte stream
NetworkIPRouting and addressing
LinkEthernet, Wi-FiHardware transmission

Sockets are programming abstractions to communicate between these layers.

In C, we use system calls like:

  • socket(): create a socket
  • bind(): assign IP/port
  • listen(): wait for connections
  • accept(): accept a connection
  • connect(): client connects to server
  • send()/recv() or read()/write(): data exchange

ALSO READ:


Socket API in C (Cheat Sheet)

FunctionRole
socket()Create socket
bind()Bind socket to IP/port
listen()Listen for incoming connections
accept()Accept a new client
connect()Initiate a connection
send()/recv()Send/receive data
close()Close socket

All of them return -1 on failure and set errno.

Simple TCP Server Code

 // tcp_server.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 9090 #define BUFFER_SIZE 1024 int main() { int server_fd, new_socket; struct sockaddr_in address; char buffer[BUFFER_SIZE] = {0}; int opt = 1; socklen_t addrlen = sizeof(address); // 1. Create socket server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd == 0) { perror("socket failed"); exit(EXIT_FAILURE); } // 2. Set socket options (optional but recommended) setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // 3. Bind address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); bind(server_fd, (struct sockaddr *)&address, sizeof(address)); // 4. Listen listen(server_fd, 5); printf("Server is listening on port %d...\n", PORT); // 5. Accept new_socket = accept(server_fd, (struct sockaddr *)&address, &addrlen); read(new_socket, buffer, BUFFER_SIZE); printf("Client says: %s\n", buffer); // 6. Reply send(new_socket, "Welcome to the server!", 23, 0); // 7. Close close(new_socket); close(server_fd); return 0; } 

Simple TCP Client Code

 // tcp_client.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <arpa/inet.h> #define PORT 9090 int main() { int sock; struct sockaddr_in serv_addr; char buffer[1024] = {0}; char *msg = "Hello, Server!"; sock = socket(AF_INET, SOCK_STREAM, 0); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(PORT); inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr); connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); send(sock, msg, strlen(msg), 0); read(sock, buffer, 1024); printf("Server reply: %s\n", buffer); close(sock); return 0; } 

How to Compile and Run

 gcc tcp_server.c -o server gcc tcp_client.c -o client 

Open two terminals and run the following commands:

  1. Run the server: ./server
  2. Run the client: ./client
The terminals running both the client and server program
The terminals running both the client and server program

Handling Multiple Clients with Threads

Let’s make it a true server that can handle many clients simultaneously using POSIX threads.

 // multi_server.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <arpa/inet.h> #define PORT 9090 void* handle_client(void* socket_desc) { int sock = *(int*)socket_desc; char buffer[1024]; read(sock, buffer, 1024); printf("Client: %s\n", buffer); send(sock, "Response from threaded server", 30, 0); close(sock); free(socket_desc); return NULL; } int main() { int server_fd, new_socket; struct sockaddr_in address; socklen_t addrlen = sizeof(address); server_fd = socket(AF_INET, SOCK_STREAM, 0); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); bind(server_fd, (struct sockaddr*)&address, sizeof(address)); listen(server_fd, 10); printf("Threaded server listening on port %d...\n", PORT); while (1) { new_socket = accept(server_fd, (struct sockaddr*)&address, &addrlen); int *new_sock = malloc(sizeof(int)); *new_sock = new_socket; pthread_t thread_id; pthread_create(&thread_id, NULL, handle_client, (void*)new_sock); pthread_detach(thread_id); // auto-free thread } close(server_fd); return 0; } 
The terminal shows a multi-threaded server with two client terminals.
The terminal shows a multi-threaded server with two client terminals.

Best Practices & Error Handling

  • Always check return values of socket functions.
  • Use perror() or strerror(errno) for diagnostics.
  • Use setsockopt() to avoid “address already in use” errors.
  • Gracefully close sockets using shutdown() + close().

Real-World Applications

Use CaseHow
Chat appsSocket server with message loop
IoT gatewayClients are sensors reporting data
Multiplayer gamesGame loop over TCP
Remote shellsUse bidirectional send/recv
File transfer toolsRead and write byte streams

Conclusion

You’ve just completed the ultimate guide to TCP client-server programming in C. From theory to a real-world multithreaded server, you’ve seen how TCP sockets are used to build reliable communication systems.

Now It’s Your Turn:

  • Modify the client to send user input
  • Make the server broadcast to all connected clients
  • Add logging, message timestamps, and authentication

Read More

Leave a Reply