← cproj

HTTP server example

c488e545674dde497946328e9a5103d538d63a9a · ovidiucs · Oct 13, 2019 18:40

+150 · 2 files changed

  • graph/sockets/Makefile +55 −0
  • graph/sockets/http_server.c +95 −0
diff --git a/graph/sockets/Makefile b/graph/sockets/Makefile
new file mode 100644
index 0000000..a5621c7
--- /dev/null
+++ b/graph/sockets/Makefile
@@ -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
diff --git a/graph/sockets/http_server.c b/graph/sockets/http_server.c
new file mode 100644
index 0000000..e377a49
--- /dev/null
+++ b/graph/sockets/http_server.c
@@ -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;
+}
+
+// ----------------------------------------------------------------