What'S The Length Of A String In Bytes

June, 2025


I'm working on an HTTP server in C and I have an open question.

HTTP responses that have a body need to specify the content length:

HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 12

foobar/1.2.3

According to what I've read, the Content-Length should be specifying the length of the body in Bytes. I'm aware of two functions in C that can give the sizes of strings, sizeof and strlen.

According to this stackoverflow post:

strlen() is used to get the length of a string stored in an array.
sizeof() is used to get the actual size of any type of data in bytes.

One would assume then, that in my HTTP response code, I would use sizeof to determine the content length. But no? For some reason, when I use sizeof the response fails to be interpreted by the original request (because the size is wrong). Instead, I need to use strlen.

So now I'm confused. If HTTP responses are supposed to specify content-length in bytes, why is it that it only works when I specify the number of characters in the string?

If you have any idea why this is happening, please feel free to shoot me an email (nicolas.gatien6@gmail.com) or ping me somewhere.

PS: Here's the state of my script. I'm following the HTTP server guide on CodeCrafters:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

int main()
{
    // Disable output buffering
    setbuf(stdout, NULL);
    setbuf(stderr, NULL);

    // You can use print statements as follows for debugging, they'll be visible when running tests.
    printf("Logs from your program will appear here!\n");

    // Uncomment this block to pass the first stage

    int server_fd, client_addr_len;
    struct sockaddr_in client_addr;

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1)
    {
        printf("Socket creation failed: %s...\n", strerror(errno));
        return 1;
    }

    // Since the tester restarts your program quite often, setting SO_REUSEADDR
    // ensures that we don't run into 'Address already in use' errors
    int reuse = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    {
        printf("SO_REUSEADDR failed: %s \n", strerror(errno));
        return 1;
    }

    struct sockaddr_in serv_addr = {
        .sin_family = AF_INET,
        .sin_port = htons(4221),
        .sin_addr = {htonl(INADDR_ANY)},
    };

    if (bind(server_fd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) != 0)
    {
        printf("Bind failed: %s \n", strerror(errno));
        return 1;
    }

    int connection_backlog = 5;
    if (listen(server_fd, connection_backlog) != 0)
    {
        printf("Listen failed: %s \n", strerror(errno));
        return 1;
    }

    printf("Waiting for a client to connect...\n");
    client_addr_len = sizeof(client_addr);

    int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
    printf("Client connected\n");

    char request_message[200];
    ssize_t bytes_received = recv(client_fd, request_message, sizeof(request_message), 0);

    char request_message_copy[200];
    strcpy(request_message_copy, request_message);

    char *endpoint;
    endpoint = strtok(request_message_copy, " ");
    endpoint = strtok(NULL, " ");

    char new_endpoint[strlen(endpoint)];
    strcpy(new_endpoint, endpoint);
    strcat(new_endpoint, "/");

    char *endpoint_token = strtok(new_endpoint, "/");

    char *endpoints[4] = {};
    int endpoint_index = 0;
    while (endpoint_token != NULL)
    {
        endpoints[endpoint_index] = endpoint_token;
        endpoint_token = strtok(NULL, "/");
        endpoint_index += 1;
    }

    char *reply = "HTTP/1.1 404 Not Found\r\n\r\n";

    if (endpoints[0] == NULL)
    {
        reply = "HTTP/1.1 200 OK\r\n\r\n";
    }
    else if (strcmp(endpoints[0], "echo") == 0)
    {
        char reply_content[200];
        sprintf(reply_content, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %lu\r\n\r\n%s", strlen(endpoints[1]), endpoints[1]);

        reply = reply_content;
    }
    else if (strcmp(endpoints[0], "user-agent") == 0)
    {

        char request_message[] = "GET /user-agent HTTP/1.1\r\nHost: localhost:4221\r\nAccept: */*\r\nUser-Agent: foobar/1.2.3\r\n\r\n";
        char user_agent_copy[strlen(request_message)];
        strcpy(user_agent_copy, request_message);

        char *user_agent;
        user_agent = strstr(user_agent_copy, "User-Agent: ");
        user_agent = strchr(user_agent, ' ');
        user_agent += 1;
        user_agent = strtok(user_agent, "\r");

        printf("AGENT: %sA", user_agent);

        char reply_content[200];
        sprintf(reply_content, "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: %lu\r\n\r\n%s", strlen(user_agent), user_agent);
        reply = reply_content;
    }

    send(client_fd, reply, strlen(reply), 0);

    close(server_fd);

    return 0;
}

📖 3 completions