diff --git a/Main.c b/Main.c
index bb8bd9f71e0789b8c1443522ce69a682a80ee52e..889467b456a7fd6094fdf04b1478e1de212d8095 100644
--- a/Main.c
+++ b/Main.c
@@ -27,18 +27,27 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/socket.h>
+#include <unistd.h>
 #include "apue.h"
+#include "HelperHeader.h"
 
 
 // Define Vars.
 #define BUFFER_SIZE 4096
+#define THREAD_MAX 50
 
 
 // Variables.
+// pthread_cond_t thread_finished;
+int threads_finished;
+int thread_free[THREAD_MAX];
+int thread_joinable[THREAD_MAX];
+pthread_t* thread_array;
 
 
 // Method Declaration.
-void* serve_request();
+void* serve_request();  // Handles processing of a request from a new thread.
+void join_threads();    // Attempts to join all finished child threads.
 
 
 /**
@@ -46,14 +55,15 @@ void* serve_request();
  * Initializes and runs program.
  */
 int main(int argc, char* argv[]) {
+    int index;
     int return_int;
     int listen_fd;
     int con_fd;
+    int thread_created;
     unsigned short port_number;
     char* media_path;
     struct sockaddr_in server_address;
     socklen_t address_len;
-    pthread_t* thread_array;
     pthread_attr_t attr;
     size_t stacksize;
 
@@ -99,7 +109,7 @@ int main(int argc, char* argv[]) {
         err_sys("Failed to bind to socket.");
     }
 
-    // Actually listen for connections.
+    // Actually listen for connections. Holds a buffer of 10 connections, if they back up.
     return_int = listen(listen_fd, 10);
     if (return_int < 0) {
         err_sys("Error on listen attempt.");
@@ -108,31 +118,104 @@ int main(int argc, char* argv[]) {
     printf("Successfully built socket. Setting up threading...\n");
 
     // Setup threading.
-    thread_array = calloc(100, sizeof(pthread_t));
+    thread_array = calloc(THREAD_MAX, sizeof(pthread_t));
     pthread_attr_init(&attr);
     pthread_attr_getstacksize(&attr, &stacksize);
     if (stacksize < 8388608) {
         stacksize = 8388608;
     }
     pthread_attr_setstacksize(&attr, (stacksize * 2));
+    // pthread_cond_init(&thread_finished, 0);
+    threads_finished = 0;
+
+    for (index = 0; index < THREAD_MAX; index++) {
+        thread_free[index] = 1;
+        thread_joinable[index] = 0;
+    }
 
     printf("Threading established. Awaiting connection...\n");
 
     // Run indefinitely, accepting new connections and creating new threads for each.
     while (1) {
+
         // Check for successful connection.
         if ((con_fd = accept(listen_fd, (struct sockaddr*) &server_address, (socklen_t*) &address_len)) >= 0) {
             printf("Recieving request...\n");
 
+            // Loop until new thread is created.
+            thread_created = 0;
+            while (thread_created == 0) {
+                // Search for first available thread.
+                index = 0;
+                while ((thread_created == 0) && (index < THREAD_MAX)) {
+                    if (thread_free[index] == 1) {
+                        // Found available thread. Changing thread status and exiting loop.
+                        thread_free[index] = 0;
+                        thread_created = 1;
+                        printf("Thread found. Starting thread #%d\n", index);
+                    } else {
+                        // Thread not available. Check next.
+                        index++;
+                    }
+                }
+
+                // Iterated through all possible threads. Check that an open one was found.
+                if (thread_created == 0) {
+                    // No open thread found.
+                    printf("No open threads found. Waiting 1 second and trying again...\n");
+                    sleep(1);
+
+                    // Check if any threads have finished. If so, join.
+                    if (threads_finished == 1) {
+                        join_threads();
+                    }
+                }
+            }
+
             // A connection has been established. Open new thread.
-            pthread_create(&thread_array[0], &attr, serve_request, (void*) NULL);
+            pthread_create(&thread_array[0], &attr, serve_request, (void*) copy_int(&index));
+        }
+
+        // Check if any threads have finished. If so, join.
+        if (threads_finished == 1) {
+            join_threads();
         }
     }
 }
 
 
-void* serve_request() {
-    printf("Request recieved and thread created!\n");
-    printf("Not doing anything about it though. Terminating thread.\n");
+/**
+ * Handles processing of a request from a new thread.
+ */
+void* serve_request(int* index) {
+    printf("\nRequest recieved and thread #%d created!\n", *index);
+    printf("Not doing anything about it though. Terminating thread.\n\n");
+
+    // Set values so that main can figure out what child threads are done executing.
+    threads_finished = 1;
+    thread_joinable[*index] = 1;
+    free(index);
+
+    // Exit thread.
     pthread_exit((void*) NULL);
 }
+
+
+/**
+ * Attempts to join all finished child threads.
+ */
+void join_threads() {
+    int index;
+
+    printf("\nAttempting to join threads...\n");
+
+    for (index = 0; index < THREAD_MAX; index++) {
+        if (thread_joinable[index] == 1) {
+            pthread_join(thread_array[index], (void*) NULL);
+            thread_free[index] = 1;
+            thread_joinable[index] = 0;
+            printf("Joining thread #%d\n", index);
+        }
+    }
+    threads_finished = 0;
+}