πŸ‡―πŸ‡΅ ζ—₯本θͺž | πŸ‡ΊπŸ‡Έ English
Advertisement

C Socket Programming Tutorial

Build a program in C that exchanges data over the network.

What is Socket Communication?

A socket is the mechanism by which two programs exchange data across a network. Web browsers, email clients, chat programs β€” any network-aware program uses sockets under the hood.
Client
Your program
β†’
TCP/IP
Internet
β†’
Server
e.g. web server

TCP vs UDP

TCP (reliable)
Guarantees delivery and ordering.
Uses: web, email, file transfer
We'll use this.
UDP (fast, lightweight)
No delivery or ordering guarantees.
Uses: video streaming, online games, DNS

Required Headers

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>        // close()
#include <arpa/inet.h>     // inet_addr(), htons()
#include <netdb.h>         // gethostbyname()
#include <sys/socket.h>    // socket(), connect(), send(), recv()
Note: these headers work on Linux/macOS. On Windows use winsock2.h.

Socket API Flow (Client Side)

A TCP client connects, exchanges data, and disconnects in five steps.
1. socket() β€” create a socket
2. connect() β€” connect to server
3. send() β€” send data
4. recv() β€” receive data
5. close() β€” close the socket
Telephone analogy: socket = pick up the phone, connect = dial, send/recv = speak/listen, close = hang up.

Build a TCP Client

Let's actually connect to a web server, send an HTTP request, and read back the response.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>

#define BUF_SIZE 4096

int main(void) {
    const char *host = "example.com";
    int port = 80;

    // ===== 1. Resolve hostname to IP address =====
    struct hostent *server = gethostbyname(host);
    if (server == NULL) {
        fprintf(stderr, "Host lookup failed\n");
        return 1;
    }

    // ===== 2. Create a socket =====
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("socket");
        return 1;
    }

    // ===== 3. Set up server address =====
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);  // port in network byte order
    memcpy(&addr.sin_addr.s_addr, server->h_addr, server->h_length);

    // ===== 4. Connect to server =====
    if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        perror("connect");
        close(sockfd);
        return 1;
    }
    printf("Connected: %s:%d\n\n", host, port);

    // ===== 5. Send HTTP request =====
    char request[BUF_SIZE];
    snprintf(request, BUF_SIZE,
        "GET / HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", host);
    send(sockfd, request, strlen(request), 0);

    // ===== 6. Receive and print response =====
    char buf[BUF_SIZE];
    int n;
    while ((n = recv(sockfd, buf, BUF_SIZE - 1, 0)) > 0) {
        buf[n] = '\0';
        printf("%s", buf);
    }

    // ===== 7. Disconnect =====
    close(sockfd);
    printf("\n\nConnection closed\n");
    return 0;
}

Compile and Run

$ gcc http_client.c -o http_client $ ./http_client Connected: example.com:80 HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 ... <html>...</html> Connection closed

Function Details

FunctionPurposeArgumentsReturns
socket()Create a socketAF_INET, SOCK_STREAM, 0socket fd (int)
gethostbyname()Hostname β†’ IP"example.com"pointer to hostent
connect()Connect to serversockfd, addr, addrlen0 = ok, -1 = fail
send()Send datasockfd, buf, len, flagsbytes sent
recv()Receive datasockfd, buf, len, flagsbytes received (0 = closed)
close()Close socketsockfd0 = ok
htons()Host-to-network short (ports)port numberconverted port

sockaddr_in Struct

struct sockaddr_in {
    short          sin_family;  // address family (AF_INET)
    unsigned short sin_port;    // port (use htons() to convert)
    struct in_addr sin_addr;    // IP address
    char           sin_zero[8]; // padding
};
htons = Host TO Network Short. CPU byte order (often little-endian) differs from network byte order (big-endian), so conversion is required.

Challenges

Challenge 1: Extract a connect function
Refactor the connection setup above into int connect_to_server(const char *host, int port), returning the socket fd. Return -1 on error.
Challenge 2: Generic send/recv helpers
Implement send_line / recv_line that send and receive one line at a time. send_line appends \r\n; recv_line reads up to \r\n.
Challenge 3: Pass host via command line
Allow ./http_client example.com 80, taking host and port from argv. See the argc/argv lesson.
Challenge 4: Save the response to a file
Add a feature to save the HTTP response to a file. See the file I/O lesson.
Next: Build an SMTP email client β†’
Share this article
Share on X