HTTP server example
+150 · 2 files changed
-
graph/sockets/Makefile+55 −0 -
graph/sockets/http_server.c+95 −0
@@ -0,0 +1,55 @@ +# Unix makefile for a C program. Set BinName to program name. + +# Definitions. +BinName = http_server +Libs = -lc + +# Options and arguments to the C compiler. +CC = clang +#CFLAGS = -g -funsigned-char -W -Wall -ggdb3 -Wunused\ +# -Wno-comment -Wno-missing-field-initializers -Wno-missing-braces -Wno-parentheses\ +# -Wno-pointer-sign -Wno-unused-parameter -Wno-unused-result $(COPTS)\ +# -Og +CFLAGS = -g \ +-Og \ +-Wall \ +-Werror \ +-Wextra \ +-Wno-comment \ +-Wno-missing-field-initializers \ +-Wno-missing-braces \ +-Wno-unused \ +-Wundef \ +-Wmissing-include-dirs \ +-Wmissing-declarations \ +-Wmissing-prototypes \ +-Wstrict-selector-match \ +-Wundeclared-selector \ +-Woverlength-strings \ +-Wimplicit-atomic-properties \ +-Wformat=2 \ +-Wno-parentheses \ +-Wcast-align \ +-Wcast-qual \ +-Wfloat-equal \ +-Wdisabled-optimization \ +-Winit-self \ +-Wredundant-decls \ +-Wshadow \ +-Wsign-conversion \ +-Wstrict-overflow=5 \ +-Wstrict-prototypes \ +-Wswitch-default \ +-Wunreachable-code \ + + +# Targets. +$(BinName): $(BinName).o + $(CC) $(LDFLAGS) $? $(Libs) -o $(BinName) +#strip $(BinName) + +$(BinName).o: $(BinName).c + $(CC) $(CFLAGS) -c -o $(BinName).o $? + +clean: + rm -f $(BinName) $(BinName).o @@ -0,0 +1,95 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> // strerror +#include <errno.h> // errno +#include <netinet/in.h> // sockaddr_in +#include <assert.h> // for assert +#include <unistd.h> // for write to fd +#include <sys/types.h> +#include <sys/socket.h> + +#define PORT 6969 + + +char response[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "\n" + "<html>" + "<head>" + "<title>PHP is the BEST</title>" + "</head>" + "<body>" + "<h1>PHP is the best</h1>" + "</body>" + "</html>"; +// ---------------------------------------------------------------- + +int main (int argc, char **argv) { + if (argc != 2) { + fprintf(stderr, "Usage: %s address\n", argv[0]); + // Return error code + return 1; + + } + + // 1. Create the socket + int server_fd = socket (AF_INET, SOCK_STREAM, 0); + + // 1.1 Check for errors + if (server_fd < 0) { + fprintf (stderr, "Could not create socket %s\n", strerror (errno)); + exit(1); + } + struct sockaddr_in serverAddr; + + memset(&serverAddr, 0, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(PORT); + + // 2. Bind the socket + int err = bind (server_fd, (struct sockaddr*) &serverAddr, sizeof(serverAddr)); + if (err < 0) { + fprintf (stderr, "Could not bind socket %s\n", strerror (errno)); + exit(1); + } + + //3. Listen to socket + // backlog - number of connection we want to support in queue + err = listen(server_fd, 69); + if (err < 0) { + fprintf (stderr, "Could not listen to socket %s\n", strerror (err)); + exit(1); + } + + //4. Keep accepting connections + // we will get back a file descriptor + for (;;) { + + struct sockaddr_in clientAddr; + socklen_t clientAddrLen = 0; + + int client_fd = accept (server_fd,(struct sockaddr*) &clientAddr, &clientAddrLen); + if (client_fd < 0 ){ + fprintf (stderr, "Could not accept connection from %s\n", strerror (errno)); + exit(1); + } + assert(clientAddrLen == sizeof(clientAddr)); + + //write to file descriptor + // response is array of chars not pointer to char. it can take the sizeof operator + write(client_fd, response, sizeof(response)); + if (err < 0) { + fprintf(stderr, "Could not send data %s\n", strerror(errno)); + } + // close the connection + err = close(client_fd); + if (err < 0) { + fprintf(stderr, "Could not close client connection from %s\n", strerror(errno)); + } + } + + return 0; +} + +// ----------------------------------------------------------------