Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Design a webserver using this template: #include <fnmatch.h> #include <errno.h>

ID: 3687970 • Letter: D

Question

Design a webserver using this template:

#include <fnmatch.h>
#include <errno.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#define BACKLOG (10)


void usage(){
fprintf(stderr,"Usage: ./homework5 [port number] [directory to serve] ");
exit(1);
}

/* char* parseRequest(char* request)
* Args: HTTP request of the form "GET /path/to/resource HTTP/1.X"
*
* Return: the resource requested "/path/to/resource"
* 0 if the request is not a valid HTTP request
*
* Does not modify the given request string.
* The returned resource should be free'd by the caller function.
*/
char* parseRequest(char* request) {
//assume file paths are no more than 256 bytes + 1 for null.
char *buffer = malloc(sizeof(char)*257);
memset(buffer, 0, 257);
  
if(fnmatch("GET * HTTP/1.*", request, 0)) return 0;

sscanf(request, "GET %s HTTP/1.", buffer);
return buffer;
}

/* Your program should take two arguments:
* 1) The port number on which to bind and listen for connections, and
* 2) The directory out of which to serve files.
*/
int main(int argc, char** argv) {
/* For checking return values. */
int retval;

/* Read the port number from the first command line argument. */
if (argc != 3){
usage();
}
int port = atoi(argv[1]);

/* Create a socket to which clients will connect. */
int server_sock = socket(AF_INET6, SOCK_STREAM, 0);
if(server_sock < 0) {
perror("Creating socket failed");
exit(1);
}

/* A server socket is bound to a port, which it will listen on for incoming
* connections. By default, when a bound socket is closed, the OS waits a
* couple of minutes before allowing the port to be re-used. This is
* inconvenient when you're developing an application, since it means that
* you have to wait a minute or two after you run to try things again, so
* we can disable the wait time by setting a socket option called
* SO_REUSEADDR, which tells the OS that we want to be able to immediately
* re-bind to that same port. See the socket(7) man page ("man 7 socket")
* and setsockopt(2) pages for more details about socket options. */
int reuse_true = 1;
retval = setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, &reuse_true,
sizeof(reuse_true));
if (retval < 0) {
perror("Setting socket option failed");
exit(1);
}

/* Create an address structure. This is very similar to what we saw on the
* client side, only this time, we're not telling the OS where to connect,
* we're telling it to bind to a particular address and port to receive
* incoming connections. Like the client side, we must use htons() to put
* the port number in network byte order. When specifying the IP address,
* we use a special constant, INADDR_ANY, which tells the OS to bind to all
* of the system's addresses. If your machine has multiple network
* interfaces, and you only wanted to accept connections from one of them,
* you could supply the address of the interface you wanted to use here. */
  

struct sockaddr_in6 addr; // internet socket address data structure
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(port); // byte order is significant
addr.sin6_addr = in6addr_any; // listen to all interfaces

  
/* As its name implies, this system call asks the OS to bind the socket to
* address and port specified above. */
retval = bind(server_sock, (struct sockaddr*)&addr, sizeof(addr));
if(retval < 0) {
perror("Error binding to port");
exit(1);
}

/* Now that we've bound to an address and port, we tell the OS that we're
* ready to start listening for client connections. This effectively
* activates the server socket. BACKLOG (#defined above) tells the OS how
* much space to reserve for incoming connections that have not yet been
* accepted. */
retval = listen(server_sock, BACKLOG);
if(retval < 0) {
perror("Error listening for connections");
exit(1);
}

while(1) {
/* Declare a socket for the client connection. */
int sock;
char buffer[256];
const char * response = "HTTP/1.0 200 OK hello client! ";

/* Another address structure. This time, the system will automatically
* fill it in, when we accept a connection, to tell us where the
* connection came from. */
struct sockaddr_in remote_addr;
unsigned int socklen = sizeof(remote_addr);

/* Accept the first waiting connection from the server socket and
* populate the address information. The result (sock) is a socket
* descriptor for the conversation with the newly connected client. If
* there are no pending connections in the back log, this function will
* block indefinitely while waiting for a client connection to be made.
* */
sock = accept(server_sock, (struct sockaddr*) &remote_addr, &socklen);
if(sock < 0) {
perror("Error accepting connection");
exit(1);
}

/* At this point, you have a connected socket (named sock) that you can
* use to send() and recv(). */

/* ALWAYS check the return value of send() and recv(). This is example
* code that you must replace. */

/* TODO: collect the request, and keep collecting until you see the
* request separator (a blank line). This is placeholder code. */
recv(sock,buffer,255,0);

/* TODO: once you've received a request, use parseRequest to pull out
* the file that was asked for. */

/* TODO: construct a valid response to that request, and send THE
* ENTIRE THING to the client. This is placeholder code. */
send(sock, response,strlen(response), 0);

/* Tell the OS to clean up the resources associated with that client
* connection, now that we're done with it. */
close(sock);
}

close(server_sock);
}

Explanation / Answer

//function specific for Windows-to be called before invoking call to socket()

int init()

{

WSADATA wsaData;

int iResult;

// Initialize Winsock

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);

if (iResult != 0)

{

  printf("WSAStartup failed: %d ", iResult);

  return 1;

}

}

//function specific for windows-to be called after all socket communication is complete

void clean()

{

WSACleanup();

}

int main()

{

while(1)

{

  init();

  server();

  clean();

}

   

    return 0;

}

void server()

{

  

        int sock, connected, bytes_recieved , true = 1;

        char send_data [1024] , recv_data[1024];      

        struct sockaddr_in server_addr,client_addr;   

        int sin_size;

         

        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {

            perror("Socket");

            exit(1);

        }

        if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1) {

            perror("Setsockopt");

            exit(1);

        }

         

        server_addr.sin_family = AF_INET;        

        server_addr.sin_port = htons(8080);    

        server_addr.sin_addr.s_addr = INADDR_ANY;

        //bzero(&(server_addr.sin_zero),8); --This is for POSIX based systems

  memset(&(server_addr.sin_zero),0,8);

        if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr))== -1)

    {

            perror("Unable to bind");

            exit(1);

        }

        if (listen(sock, 5) == -1)

  {

            perror("Listen");

            exit(1);

        }

   

  printf(" MyHTTPServer waiting on port 8080");

        fflush(stdout);

         

            sin_size = sizeof(struct sockaddr_in);

            connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);

           // printf(" I got a connection from (%s , %d)",

                //   inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));

   char kk[9999];

   recv(connected,kk,sizeof(kk),0);

   printf(" Received:%s",kk);

    

   char xx[9999];

   strcpy(xx,"HTTP/1.1 200 OK Content-length: 47 Content-Type: text/html <html><body><H1>Hello Kartik</H1></body></html>");

    

   int c=send(connected,&xx,sizeof(xx),0);

   printf(" STATUS:%d",c);

      

   printf(" Sent : %s ",xx);

    

            close(sock);

   WSACleanup();

}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote