diff --git a/Main.c b/Main.c index 53de1e4e56bbce831adb1b9a48c20fbb1759215d..9acd308462512791259df0349815b888941a7e1c 100644 --- a/Main.c +++ b/Main.c @@ -41,7 +41,7 @@ // Variables. struct conn_obj { int* index; - int conn_fd; + int* conn_fd; struct sockaddr_in* client_address; }; @@ -67,8 +67,8 @@ int main(int argc, char* argv[]) { int index; int return_int; int listen_fd; - int con_fd; int thread_created; + int* conn_fd; char* media_path; struct sockaddr_in* client_address; socklen_t address_len; @@ -92,7 +92,7 @@ int main(int argc, char* argv[]) { // Get path to media. media_path = calloc(BUFFER_SIZE, sizeof(char*)); if (getcwd(media_path, BUFFER_SIZE) == NULL) { - err_sys("Failed to get absolute path."); + err_sys("Failed to get absolute path"); } else { strcat(media_path, "/Media"); } @@ -100,7 +100,7 @@ int main(int argc, char* argv[]) { // Creates socket and sets listener file descriptor. if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { - err_sys("Failed to set socket."); + err_sys("Failed to set socket"); } // Sets bytes at memory location to 0. Mandatory, supposedly. @@ -108,19 +108,22 @@ int main(int argc, char* argv[]) { // Set server info. server_address.sin_family = AF_INET; // Addressing scheme. - server_address.sin_addr.s_addr = htons(INADDR_ANY); // Allow any ip to connect. + server_address.sin_addr.s_addr = htonl(INADDR_ANY); // Allow any ip to connect. server_address.sin_port = htons(port_number); // Port to listen on. // Prepare to listen. return_int = bind(listen_fd, (struct sockaddr *) &server_address, sizeof(server_address)); if (return_int < 0) { - err_sys("Failed to bind to socket."); + err_sys("Failed to bind to socket"); } + char* temp_string = inet_ntoa(server_address.sin_addr); + printf("Server IP: %s\n", temp_string); + // 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."); + err_sys("Error on listen attempt"); } printf("Successfully built socket. Setting up threading...\n"); @@ -133,7 +136,6 @@ int main(int argc, char* argv[]) { stacksize = 8388608; } pthread_attr_setstacksize(&attr, (stacksize * 2)); - // pthread_cond_init(&thread_finished, 0); threads_finished = 0; for (index = 0; index < THREAD_MAX; index++) { @@ -148,7 +150,8 @@ int main(int argc, char* argv[]) { // Check for successful connection. client_address = calloc(1, sizeof(struct sockaddr)); - if ((con_fd = accept(listen_fd, (struct sockaddr*) client_address, (socklen_t*) &address_len)) >= 0) { + conn_fd = calloc(1, sizeof(int)); + if ((*conn_fd = accept(listen_fd, (struct sockaddr*) client_address, (socklen_t*) &address_len)) >= 0) { printf("Recieving request...\n"); // Loop until new thread is created. @@ -184,8 +187,7 @@ int main(int argc, char* argv[]) { // A connection has been established. Open new thread. char* ip = inet_ntoa(client_address->sin_addr); printf("Client IP: %s\n", ip); - // pthread_create(&thread_array[0], &attr, serve_request, (void*) copy_int(&index)); - pthread_create(&thread_array[0], &attr, serve_request, (void*) &((struct conn_obj) {copy_int(&index), -1, client_address})); + pthread_create(&thread_array[0], &attr, serve_request, (void*) &((struct conn_obj) {copy_int(&index), conn_fd, client_address})); } // Check if any threads have finished. If so, join. @@ -256,4 +258,5 @@ void send_response(struct conn_obj connection) { strcat(response_buffer, "\r\n"); printf("%s\n", response_buffer); + // write(*connection.conn_fd, response_buffer, (strlen(response_buffer) + 1)); } diff --git a/Main_No_Threads.c b/Main_No_Threads.c new file mode 100644 index 0000000000000000000000000000000000000000..826662d797284079f589179c6c24da3108b6889e --- /dev/null +++ b/Main_No_Threads.c @@ -0,0 +1,205 @@ +/** + * Brandon Rodriguez + * CS 3240 + * 12-05-17 + * a6 (Assignment 7) + */ + + +/** + * Description: + * + */ + + +/** + * Known Issues: + * + */ + + +// Import headers. +#include <arpa/inet.h> +#include <ctype.h> +#include <netdb.h> +#include <pthread.h> +#include <stdio.h> +#include <string.h> +#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. +struct conn_obj { + int* index; + int* conn_fd; + struct sockaddr_in* client_address; +}; + +struct sockaddr_in server_address; +unsigned short port_number; + + +// Method Declaration. +void* serve_request(); // Handles processing of a request from a new thread. +void join_threads(); // Attempts to join all finished child threads. +void send_response(); // Generates and sends http response to requesting client. + + +/** + * Program's main. + * Initializes and runs program. + */ +int main(int argc, char* argv[]) { + int index; + int return_int; + int listen_fd; + int* conn_fd; + char* media_path; + struct sockaddr_in* client_address; + socklen_t address_len; + + // Check that valid number of args have been given. + if (argc < 2) { + printf("Need to provide port number.\n"); + exit(1); + } else if (argc > 2) { + printf("Please provide exactly one arg of port number.\n"); + exit(1); + } + + printf("Building socket...\n"); + + port_number = atoi(argv[1]); + address_len = sizeof(server_address); + + // Get path to media. + media_path = calloc(BUFFER_SIZE, sizeof(char*)); + if (getcwd(media_path, BUFFER_SIZE) == NULL) { + err_sys("Failed to get absolute path"); + } else { + strcat(media_path, "/Media"); + } + printf("Media Path: %s\n\n", media_path); + + // Creates socket and sets listener file descriptor. + if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { + err_sys("Failed to set socket"); + } + + // Sets bytes at memory location to 0. Mandatory, supposedly. + memset(&server_address, '0', sizeof(server_address)); + + // Set server info. + server_address.sin_family = AF_INET; // Addressing scheme. + server_address.sin_addr.s_addr = htonl(INADDR_ANY); // Allow any ip to connect. + server_address.sin_port = htons(port_number); // Port to listen on. + + // Prepare to listen. + return_int = bind(listen_fd, (struct sockaddr *) &server_address, sizeof(server_address)); + if (return_int < 0) { + err_sys("Failed to bind to socket"); + } + + // 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"); + } + + printf("Successfully built socket. Awaiting connection...\n\n"); + + // Run indefinitely, accepting new connections and creating new threads for each. + while (1) { + + // Check for successful connection. + client_address = calloc(1, sizeof(struct sockaddr)); + conn_fd = calloc(1, sizeof(int)); + if ((*conn_fd = accept(listen_fd, (struct sockaddr*) client_address, (socklen_t*) &address_len)) >= 0) { + printf("Recieving request...\n"); + + // A connection has been established. Generating response.. + char* ip = inet_ntoa(client_address->sin_addr); + printf("Client IP: %s Connection FD: %d\n", ip, *conn_fd); + index = 0; + + char* response_buffer_1 = calloc(BUFFER_SIZE, sizeof(char)); + char* response_buffer_2 = calloc(BUFFER_SIZE, sizeof(char)); + + // First setup desired content. + strcat(response_buffer_2, "<body><h1>This is a response.</h1></body>"); + + // Then set up response header. + strcat(response_buffer_1, "HTTP/1.2 200 Okay\r\n"); + strcat(response_buffer_1, "Server: Cat/1.0.0"); + strcat(response_buffer_1, "\r\n"); + strcat(response_buffer_1, "Content-Type: text/html\r\n"); + strcat(response_buffer_1, "Content-Length: "); + char* temp_string = calloc(BUFFER_SIZE, sizeof(char)); + sprintf(temp_string, "%ld", strlen(response_buffer_2)); + strcat(response_buffer_1, temp_string); + strcat(response_buffer_1, "\r\n\r\n"); + + + printf("%s\n", response_buffer_1); + // Send header. + send(*conn_fd, response_buffer_1, (strlen(response_buffer_1) + 1), 0); + // Send actual content. + send(*conn_fd, response_buffer_2, (strlen(response_buffer_2) + 1), 0); + } + } +} + + +/** + * Handles processing of a request from a new thread. + */ +void* serve_request(struct conn_obj* connection) { + printf("\nRequest recieved and thread #%d created!\n", *connection->index); + send_response(connection); + printf("Terminating thread.\n\n"); + + // Set values so that main can figure out what child threads are done executing. + free(connection->index); + free(connection->client_address); + + return connection; +} + + +/** + * Generates and sends http response to requesting client. + */ +void send_response(struct conn_obj connection) { + // char* temp_string; + char* response_buffer = calloc(BUFFER_SIZE, sizeof(char)); + + strcat(response_buffer, "HTTP/1.2 200 Okay\r\n"); + + // strcat(response_buffer, "Server: "); + // temp_string = inet_ntoa(server_address.sin_addr); + // strcat(response_buffer, temp_string); + // strcat(response_buffer, ":"); + // temp_string = calloc(10, sizeof(char*)); + // sprintf(temp_string, "%u", port_number); + // strcat(response_buffer, temp_string); + strcat(response_buffer, "Server: Cat"); + strcat(response_buffer, "\r\n"); + strcat(response_buffer, "Content-Type: text/html\r\n"); + strcat(response_buffer, "Content-Length: "); + strcat(response_buffer, "\r\n\r\n"); + + printf("%s\n", response_buffer); + printf("%d\n", *connection.conn_fd); + // write(*connection.conn_fd, response_buffer, (strlen(response_buffer) + 1)); + send(*connection.conn_fd, response_buffer, (strlen(response_buffer) + 1), 0); +} diff --git a/makefile b/makefile index 8cd152cf11d15f66316b607e3112fde8c83fc154..66789df3cbacef45ae4b93fdaa615f65769709b8 100644 --- a/makefile +++ b/makefile @@ -1,2 +1,4 @@ all: - gcc -Wall -Wpedantic -std=c99 *.c -g -o a6 -pthread -lmagic + gcc -Wall -Wpedantic -std=c99 Main.c error.c HelperFunctions.c -g -o a6 -pthread -lmagic +test: + gcc -Wall -Wpedantic -std=c99 Main_No_Threads.c error.c HelperFunctions.c -g -o a6 -pthread -lmagic