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