Web server works on Linux, multithreaded server is now under async
This commit is contained in:
parent
3b3c421bae
commit
985d2d8d77
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user