network-protocols

Definition

Hypertext Transfer Protocol (HTTP)

HTTP (Hypertext Transfer Protocol) is an application layer protocol for distributed, collaborative, hypermedia information systems.

Client Implementations

C Client Implementation

See: getaddrinfo, socket, connect, freeaddrinfo, send, recv, close

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
 
int main(int argc, char *argv[]) {
    if (argc < 2) return 1;
 
    // 1. resolve host (ipv4 & ipv6)
    struct addrinfo hints = {0};
	hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // Wildcard IP (0.0.0.0 or ::)
 
    struct addrinfo *res;
    if (getaddrinfo(argv[1], "80", &hints, &res) != 0) return 2;
 
    // 2. create socket & connect
    int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    if (s < 0 || connect(s, res->ai_addr, res->ai_addrlen) < 0) {
        freeaddrinfo(res);
        return 3;
    }
    freeaddrinfo(res); // Clean up memory
 
    // 3. send http request
    char req[1024];
    snprintf(req, sizeof(req), "GET / HTTP/1.0\r\nHost: %s\r\n\r\n", argv[1]);
    send(s, req, strlen(req), 0);
 
    // 4. receive response
    char buf[1024];
    int n;
    while ((n = recv(s, buf, sizeof(buf) - 1, 0)) > 0) {
        buf[n] = 0;
        printf("%s", buf);
    }
 
    close(s);
    return 0;
}

Server Implementations

C Server Implementation

See: getaddrinfo, socket, connect, freeaddrinfo, bind, listen, send, accept, recv, close

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
 
int main() {
    // 1. setup hints for "binding" (AI_PASSIVE)
    struct addrinfo hints = {0};
	hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // Wildcard IP (0.0.0.0 or ::)
 
    struct addrinfo *res;
    getaddrinfo(NULL, "8080", &hints, &res);
 
    // 2. create socket, set reuse, bind, and listen
    int s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
    
    // critical: allows restarting server immediately after crash/close
    int opt = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 
    if (bind(s, res->ai_addr, res->ai_addrlen) < 0) return 1;
    listen(s, 10); // backlog of max 10 queued connections
    freeaddrinfo(res);
 
    printf("Listening on port 8080...\n");
 
    // 3. accept loop
    while (1) {
		struct sockaddr_storage client_addr;
	    socklen_t client_addr_len = sizeof(client_addr);
	
        int client_fd = accept(s, &client_addr, &addr_len); // NULL: we don't care about client IP
        
        // Read request (discarding content for simplicity)
        char buf[1024];
        recv(client_fd, buf, sizeof(buf), 0);
 
        // Send static response
        const char *resp = 
            "HTTP/1.0 200 OK\r\n"
            "Content-Type: text/plain\r\n"
            "\r\n"
            "Hello from C stdlib!";
        
        send(client_fd, resp, strlen(resp), 0);
        close(client_fd);
    }
    
    return 0;
}