Web server works on Linux, multithreaded server is now under async

This commit is contained in:
TriantaTV 2023-09-30 04:08:29 -05:00
parent 3b3c421bae
commit 985d2d8d77

View File

@ -28,7 +28,7 @@
//= History: KJC (12/29/00) - Genesis (from server.c) = //= History: KJC (12/29/00) - Genesis (from server.c) =
//= HF (01/25/01) - Ported to multi-platform environment = //= HF (01/25/01) - Ported to multi-platform environment =
//============================================================================= //=============================================================================
#define UNIX // WIN for Windows environment, UNIX for BSD or LINUX env. #define WIN // WIN for Windows environment, UNIX for BSD or LINUX env.
//----- Include files --------------------------------------------------------- //----- Include files ---------------------------------------------------------
#include <stdio.h> // Needed for printf() #include <stdio.h> // Needed for printf()
@ -36,7 +36,7 @@
#include <string.h> // Needed for strcpy() and strlen() #include <string.h> // Needed for strcpy() and strlen()
#include <fcntl.h> // Needed for file i/o constants #include <fcntl.h> // Needed for file i/o constants
#include <sys/stat.h> // Needed for file i/o constants #include <sys/stat.h> // Needed for file i/o constants
#include <thread> #include <future>
/* FOR BSD UNIX/LINUX ---------------------------------------------------- */ /* FOR BSD UNIX/LINUX ---------------------------------------------------- */
#ifdef UNIX #ifdef UNIX
@ -53,10 +53,14 @@
#include <stddef.h> // Needed for _threadid #include <stddef.h> // Needed for _threadid
#include <process.h> // Needed for _beginthread() and _endthread() #include <process.h> // Needed for _beginthread() and _endthread()
#include <io.h> // Needed for open(), close(), and eof() #include <io.h> // Needed for open(), close(), and eof()
#include <winsock2.h>
#include <windows.h> // Needed for all Winsock stuff #include <windows.h> // Needed for all Winsock stuff
// Lazy struct fixes
typedef int32_t socklen_t;
#endif #endif
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
//----- HTTP response messages ---------------------------------------------- //----- HTTP response messages ----------------------------------------------
#define OK_IMAGE "HTTP/1.0 200 OK\nContent-Type:image/gif\n\n" #define OK_IMAGE "HTTP/1.0 200 OK\nContent-Type:image/gif\n\n"
#define OK_TEXT "HTTP/1.0 200 OK\nContent-Type:text/html\n\n" #define OK_TEXT "HTTP/1.0 200 OK\nContent-Type:text/html\n\n"
@ -68,6 +72,7 @@
#define PORT_NUM 7080 // Port number for a Web server #define PORT_NUM 7080 // Port number for a Web server
//----- Function prototypes ------------------------------------------------- //----- Function prototypes -------------------------------------------------
void ClientRequest(int server_s, int client_s);
/* FOR WIN --------------------------------------------------------------- */ /* FOR WIN --------------------------------------------------------------- */
#ifdef WIN #ifdef WIN
void handle_get(void *in_arg); // Thread function to handle GET void handle_get(void *in_arg); // Thread function to handle GET
@ -112,27 +117,40 @@ int main(void)
// Create a socket, fill-in address information, and then bind it // Create a socket, fill-in address information, and then bind it
server_s = socket(AF_INET, SOCK_STREAM, 0); server_s = socket(AF_INET, SOCK_STREAM, 0);
if (server_s == -1)
{
printf("ERROR - Unable to create socket on server\n");
exit(1);
}
server_addr.sin_family = AF_INET; server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT_NUM); server_addr.sin_port = htons(PORT_NUM);
server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr)); int bindRet = bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (bindRet == -1)
{
printf("ERROR - Unable to bind socket\n");
exit(1);
}
// Listen for connections and then accept
listen(server_s, 100);
// Main loop to listen, accept, and then spin-off a thread to handle the GET // Main loop to listen, accept, and then spin-off a thread to handle the GET
while (1) while (1)
{ {
// Listen for connections and then accept
listen(server_s, 100);
addr_len = sizeof(client_addr); addr_len = sizeof(client_addr);
client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len); client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);
if (client_s == 0) if (client_s == -1)
{ {
printf("ERROR - Unable to create socket \n"); perror("ERROR - Unable to create socket to client\n");
exit(1); continue;
} }
std::async(std::launch::async, ClientRequest, server_s, client_s);
/* FOR UNIX/LINUX ---------------------------------------------------- */ /* FOR UNIX/LINUX ---------------------------------------------------- */
#ifdef UNIX #ifdef UNIX
/*
// Spin-off a child process by fork // Spin-off a child process by fork
nChild_proc_id = fork(); nChild_proc_id = fork();
@ -141,25 +159,28 @@ int main(void)
{ {
child_proc(server_s, client_s); child_proc(server_s, client_s);
} }
*/
#endif #endif
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
/* FOR WIN ----------------------------------------------------------- */ /* FOR WIN ----------------------------------------------------------- */
#ifdef WIN #ifdef WIN
/*
// Spin-off a thread to handle this request (pass only client_s) // Spin-off a thread to handle this request (pass only client_s)
if (_beginthread(handle_get, 4096, (void *)client_s) < 0) if (_beginthread(handle_get, 4096, (void *)client_s) < 0)
{ {
printf("ERROR - Unable to create thread \n"); printf("ERROR - Unable to create thread \n");
exit(1); exit(1);
} }
*/
#endif #endif
/* ------------------------------------------------------------------- */ /* ------------------------------------------------------------------- */
} }
close(server_s);
/* FOR UNIX/LINUX ------------------------------------------------------ */ /* FOR UNIX/LINUX ------------------------------------------------------ */
#ifdef UNIX #ifdef UNIX
// Close the server socket // Close the server socket
close(server_s); //close(server_s);
#endif #endif
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -177,6 +198,61 @@ int main(void)
return (1); return (1);
} }
void ClientRequest(int server_s, int client_s) {
char in_buf[BUF_SIZE]; // Input buffer for GET resquest
char out_buf[BUF_SIZE]; // Output buffer for HTML response
char *file_name; // File name
unsigned int fh; // File handle
unsigned int buf_len; // Buffer length for file reads
unsigned int retcode; // Return code
// Receive the GET request from the Web browser
retcode = recv(client_s, in_buf, BUF_SIZE, 0);
// Handle the GET if there is one (see note #3 in the header)
if (retcode != -1)
{
// Parse out the filename from the GET request
strtok(in_buf, " ");
file_name = strtok(NULL, " ");
// Open the requested file
// - Start at 2nd char to get rid of leading "\"
#ifdef WIN
fh = open(&file_name[1], O_RDONLY | O_BINARY, S_IREAD | S_IWRITE);
#endif
#ifdef UNIX
fh = open(&file_name[1], O_RDONLY, S_IREAD | S_IWRITE);
#endif
// Generate and send the response (404 if could not open the file)
if (fh == -1)
{
printf("File %s not found - sending an HTTP 404 \n", &file_name[1]);
strcpy(out_buf, NOTOK_404);
send(client_s, out_buf, strlen(out_buf), 0);
strcpy(out_buf, MESS_404);
send(client_s, out_buf, strlen(out_buf), 0);
}
else
{
printf("File %s is being sent \n", &file_name[1]);
if (strstr(file_name, ".gif") != NULL)
strcpy(out_buf, OK_IMAGE);
else
strcpy(out_buf, OK_TEXT);
send(client_s, out_buf, strlen(out_buf), 0);
do {
buf_len = read(fh, out_buf, BUF_SIZE);
send(client_s, out_buf, buf_len, 0);
} while (buf_len != 0);
close(fh);
}
}
// Close the client socket and end the thread
close(client_s);
}
/* FOR WIN --------------------------------------------------------------- */ /* FOR WIN --------------------------------------------------------------- */
#ifdef WIN #ifdef WIN
//=========================================================================== //===========================================================================
@ -194,7 +270,7 @@ void handle_get(void *in_arg)
unsigned int retcode; // Return code unsigned int retcode; // Return code
// Set client_s to in_arg // Set client_s to in_arg
client_s = (unsigned int)in_arg; client_s = (unsigned int&)in_arg;
// Receive the GET request from the Web browser // Receive the GET request from the Web browser
retcode = recv(client_s, in_buf, BUF_SIZE, 0); retcode = recv(client_s, in_buf, BUF_SIZE, 0);
@ -290,11 +366,10 @@ void child_proc(int server_s, int client_s)
strcpy(out_buf, OK_TEXT); strcpy(out_buf, OK_TEXT);
send(client_s, out_buf, strlen(out_buf), 0); send(client_s, out_buf, strlen(out_buf), 0);
while (fh != EOF) do {
{
buf_len = read(fh, out_buf, BUF_SIZE); buf_len = read(fh, out_buf, BUF_SIZE);
send(client_s, out_buf, buf_len, 0); send(client_s, out_buf, buf_len, 0);
} } while (buf_len != 0);
close(fh); close(fh);
} }
} }