Skip to content

Instantly share code, notes, and snippets.

@Hermann-SW
Created June 23, 2025 17:38
Show Gist options
  • Save Hermann-SW/c63c88040276b135a600a440d23520ad to your computer and use it in GitHub Desktop.
Save Hermann-SW/c63c88040276b135a600a440d23520ad to your computer and use it in GitHub Desktop.
single threaded http server for distribution of disjoint bases from a range to geneferg on many CPUs/GPUs
/* based on:
https://medium.com/@justup1080/tutorial-creating-a-minimalist-http-server-in-c-2303d140c725
gcc -Wall -Wextra -pedantic range_http.c -o range_http
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <assert.h>
#define BUFFER_SIZE 16000
struct Server {
int domain;
int port;
int service;
int protocol;
int backlog;
u_long interface;
int socket;
struct sockaddr_in address;
void (*launch)(struct Server *server);
};
struct Server server_Constructor(int domain, int port, int service, int protocol, int backlog, u_long interface, void (*launch)(struct Server *server)) {
struct Server server;
server.domain = domain;
server.service = service;
server.port = port;
server.protocol = protocol;
server.backlog = backlog;
server.address.sin_family = domain;
server.address.sin_port = htons(port);
server.address.sin_addr.s_addr = htonl(interface);
server.socket = socket(domain, service, protocol);
if (server.socket < 0) {
perror("Failed to initialize/connect to socket...\n");
exit(EXIT_FAILURE);
}
if (bind(server.socket, (struct sockaddr*)&server.address, sizeof(server.address)) < 0) {
perror("Failed to bind socket...\n");
exit(EXIT_FAILURE);
}
if (listen(server.socket, server.backlog) < 0) {
perror("Failed to start listening...\n");
exit(EXIT_FAILURE);
}
server.launch = launch;
return server;
}
int begin=0;
int end=0;
int step=0;
void launch(struct Server *server) {
char buffer[BUFFER_SIZE];
while (1) {
if ((step>0 && begin>=end) || (step<0 && begin<=end))
exit(0);
// printf("=== WAITING FOR CONNECTION === \n");
int addrlen = sizeof(server->address);
int new_socket = accept(server->socket, (struct sockaddr*)&server->address, (socklen_t*)&addrlen);
ssize_t bytesRead = read(new_socket, buffer, BUFFER_SIZE - 1);
if (bytesRead >= 0) {
buffer[bytesRead] = '\0'; // Null terminate the string
putchar('.'); fflush(stdout); // puts(buffer);
} else {
perror("Error reading buffer...\n");
}
sprintf(buffer,"HTTP/1.1 200 OK\r\n\r\n%d\n",begin);
begin+=step;
write(new_socket, buffer, strlen(buffer));
close(new_socket);
}
}
int main(int argc, char *argv[]) {
assert(argc == 5);
int port = atoi(argv[1]);
begin = atoi(argv[2]);
end = atoi(argv[3]);
step = atoi(argv[4]);
struct Server server = server_Constructor(AF_INET, port, SOCK_STREAM, 0, 10, INADDR_ANY, launch);
server.launch(&server);
return 0;
}
@Hermann-SW
Copy link
Author

range_http arguments are localhost port, from, to and increment.
Half-open range including from and excluding to is generated.
This script demonstrates the use:

hermann@RX-Vega56:~$ cat demo 
#!/bin/bash
h="$1"
while true
do
  b=`curl $h -s`
  if [ "$b" == "" ]
  then
    exit
  fi
  echo $b
done
hermann@RX-Vega56:~$ 

Even numbers from 10 to 18:

pi@raspberrypi5:~/http $ ./range_http raspberrypi5:8000 10 20 2 && echo
.....
pi@raspberrypi5:~/http $ 
hermann@RX-Vega56:~$ ./demo raspberrypi5:8000
10
12
14
16
18
hermann@RX-Vega56:~$ 

Even numbers from 20 down to 12:

pi@raspberrypi5:~/http $ ./range_http 8001 20 10 -2 && echo
.....
pi@raspberrypi5:~/http $ 
hermann@RX-Vega56:~$ ./demo raspberrypi5:8001
20
18
16
14
12
hermann@RX-Vega56:~$ 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment