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

Question Re-write the server below as a true web sever using GET command for HTT

ID: 3671102 • Letter: Q

Question

Question

Re-write the server below as a true web sever using GET command for HTTP 1.1 It should accept the Host message. The server should maintain a cache of file recently fetched from the disk and serve requests from cache when possible.

THE TRANSPORT LAYER CHAP. 6

/

* This page contains a client program that can request a file from the server program

* on the next page. The server responds by sending the whole file.

*/

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#define SERVER PORT 12345 /* arbitrary, but client & server must agree */

#define BUF SIZE 4096 /* block transfer size */

int main(int argc, char **argv)

{

int c, s, bytes;

char buf[BUF SIZE]; /* buffer for incoming file */

struct hostent *h; /* info about server */

struct sockaddr in channel; /* holds IP address */

if (argc != 3) fatal("Usage: client server-name file-name");

h = gethostbyname(argv[1]); /* look up host’s IP address */

if (!h) fatal("gethostbyname failed");

s = socket(PF INET, SOCK STREAM, IPPROTO TCP);

if (s <0) fatal("socket");

memset(&channel, 0, sizeof(channel));

channel.sin family= AF INET;

memcpy(&channel.sin addr.s addr, h->h addr, h->h length);

channel.sin port= htons(SERVER PORT);

c = connect(s, (struct sockaddr *) &channel, sizeof(channel));

if (c < 0) fatal("connect failed");

/

* Connection is now established. Send file name including 0 byte at end. */

write(s, argv[2], strlen(argv[2])+1);

/

* Go get the file and write it to standard output. */

while (1) {

bytes = read(s, buf, BUF SIZE); /* read from socket */

if (bytes <= 0) exit(0); /* check for end of file */

write(1, buf, bytes); /* write to standard output */

}

}

fatal(char *string)

{

printf("%s ", string);

exit(1);

}

Figure 6-6. Client code using sockets. The server code is on the next page.

SEC. 6.1 THE TRANSPORT SERVICE 505

#include <sys/types.h> /* This is the server code */

#include <sys/fcntl.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#define SERVER PORT 12345 /* arbitrary, but client & server must agree */

#define BUF SIZE 4096 /* block transfer size */

#define QUEUE SIZE 10

int main(int argc, char *argv[])

{

int s, b, l, fd, sa, bytes, on = 1;

char buf[BUF SIZE]; /* buffer for outgoing file */

struct sockaddr in channel; /* holds IP address */

/

* Build address structure to bind to socket. */

memset(&channel, 0, sizeof(channel)); /* zero channel */

channel.sin family = AF INET;

channel.sin addr.s addr = htonl(INADDR ANY);

channel.sin port = htons(SERVER PORT);

/

* Passive open. Wait for connection. */

s = socket(AF INET, SOCK STREAM, IPPROTO TCP); /* create socket */

if (s < 0) fatal("socket failed");

setsockopt(s, SOL SOCKET, SO REUSEADDR, (char *) &on, sizeof(on));

b = bind(s, (struct sockaddr *) &channel, sizeof(channel));

if (b < 0) fatal("bind failed");

l = listen(s, QUEUE SIZE); /* specify queue size */

if (l < 0) fatal("listen failed");

/

* Socket is now set up and bound. Wait for connection and process it. */

while (1) {

sa = accept(s, 0, 0); /* block for connection request */

if (sa < 0) fatal("accept failed");

read(sa, buf, BUF SIZE); /* read file name from socket */

/

* Get and return the file. */

fd = open(buf, O RDONLY); /* open the file to be sent back */

if (fd < 0) fatal("open failed");

while (1) {

bytes = read(fd, buf, BUF SIZE); /* read from file */

if (bytes <= 0) break; /* check for end of file */

write(sa, buf, bytes); /* write bytes to socket */

}

close(fd); /* close file */

close(sa); /* close connection */

}

}

Explanation / Answer

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/time.h>

#include <math.h>

// Sockets includes.

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

// Constants

#define HOSTLEN 256

#define BUFLEN 40960

#define CMDLEN 256

// Cache data structures

char* cache;

int cache_size = 0;

int num_compacts = 0;   // Spread number of compactions over total sites visited.

void surf(int argc, char **argv);

void browse(char* host, char* page, int id);

int main()

{

    int size=10;

    char* surf_arg[10];

    surf_arg[0]="./websurf";

    surf_arg[1]="-f";

    surf_arg[2]="urls.txt";

    surf_arg[3]="-s";

    surf_arg[4]="1";

    surf_arg[5]="-n";

    surf_arg[6]="1";

    surf_arg[7]="-c";

    surf_arg[8]="1";

    surf_arg[9]="";

    surf(size,surf_arg);

    return 0;

}

void surf(int argc, char **argv)

{

    // Program arguments

    int s, num_websites = 0, page_index;

    char filename[HOSTLEN];

    FILE* fp;

    struct timeval tval;

    struct timezone tzone;

    // Web host and pages

    char host[HOSTLEN];

    char **pages;

    int num_pages = 0;

    // Get program arguments.

    for (s=1; s<argc; s++) {

        // Filename

        if ((strcmp (argv[s],"-f")) == 0) {

            s++;

            strcpy (filename, argv[s]);

        }

        // Number of compactions

        else if ((strcmp (argv[s],"-c")) == 0) {

            s++;

            num_compacts = atoi (argv[s]);

        }

        // Number of websites to randomly visit

        else if ((strcmp (argv[s],"-n")) == 0) {

            s++;

            num_websites = atoi (argv[s]);

        }

        // Cache size

        else if ((strcmp (argv[s],"-s")) == 0) {

            s++;

            cache_size = atoi (argv[s]);

        }

        // Print usage

        else {

            printf ("Usage: ./websurf -f <filename> -s <queue size> -n <# websites to visit> -c <# of compactions> ");

            exit (0);

        }

    }

    // Print program arguments

    printf ("Filename: %s ", filename);

    printf ("Number of websites to access = %i ", num_websites);

    printf ("Cache size = %i ", cache_size);

    printf ("Number of times to compact memory = %i ", num_compacts);

    // Open file and store host and page names into pages array.

    fp = fopen (filename, "r+");

    if (fp == NULL) {

        printf ("Error - could not open URLs file ");

        exit (-1);

    }

    fscanf (fp, "%i %s ", &num_pages, host);

    pages = (char**) calloc (num_pages, sizeof(char*));

    for (s=0; s<num_pages; s++) {

        pages[s] = (char*) calloc (HOSTLEN, sizeof(char));

        fscanf (fp, "%s ", pages[s]);

        //printf ("URL: %s%s ", host, pages[s]);

    }

    // Seed random number generator

    gettimeofday (&tval, &tzone);

    srand48 (tval.tv_usec);

    // Start browsing randomly in list of available pages.

    for (s=0; s<num_websites; s++) {

        page_index = 0; // Get random page index.

        printf ("Page index %i URL: %s%s ", page_index, host, pages[page_index]);

        browse (host, pages[page_index], page_index);

    }

}

/**********************************************************************************/

// Main function where host and page names are initialized, and threads are created.

void browse (char* host, char* page, int id) {

    //Socket data structures - Need only 1 socket to browse many pages.

    int sckt;

    struct hostent *he;

    struct sockaddr_in srvaddr;

    char cmd[CMDLEN]; // Command line to send to web server

    // Webpage data structures

    int nread;

    char buf[BUFLEN];

    char *body;

    int temp_fd;

    int child;

    int result;

    char tempfilename[16];

    int webpage_size = 0; // Initialize page size to 0

     

    // Child process

    int pid;

     

    // create TCP connection to web server

    if ((sckt = socket(AF_INET, SOCK_STREAM, 0)) == -1)

        perror("socket"), exit(1);

    if ((he = gethostbyname(host)) == NULL)

        perror("gethostbyname"), exit(1);

    //bzero(&srvaddr, sizeof(srvaddr));

    srvaddr.sin_family = AF_INET;

    srvaddr.sin_addr.s_addr = *(int *)(he->h_addr_list[0]);

    srvaddr.sin_port = htons (80);

    if (connect(sckt, (struct sockaddr *)&srvaddr, sizeof(srvaddr)) == -1)

            perror("connect"), exit(1);

    // create GET request

    sprintf(cmd, "GET %s HTTP/1.1 Host: %s ", page, host);

    printf ("cmd: %s ", cmd);

    // send GET request

    if (write(sckt, cmd, strlen(cmd)) != strlen(cmd))

        perror("GET write"), exit(1);

    // read response

    if ((nread = read(sckt, buf, BUFLEN)) < 0)

        perror("read"), exit(1);

    if (nread >= BUFLEN)

        fprintf(stderr, "web: need bigger (HTTP) read buffer "), exit(1);

    buf[nread] = 0;

    printf("web: nread = %d ", nread);

    if (nread < 512) printf("web: response: %s ", buf);

    else printf("web: initial chars of response: %.300s ", buf);

    // check return code

    //if (strncmp(buf, "HTTP/1.1 200 OK", 15))

    // fprintf(stderr, "web: GET failed "), exit(1);

    // bail out if chunked encoding

    if (strstr(buf, "Transfer-Encoding: chunked")) {

        fprintf(stderr, "web: can't handle chunked encoding ");

        //pthread_exit(NULL);

        exit (0);

    }

    // trim HTTP protocol header from response

    if ((body = strstr(buf, " ")) == NULL)

        fprintf(stderr, "web: can't find end of HTTP header in response "), exit(1);

    body = body + 4;

    // create & open temp file

    sprintf(tempfilename, "temp%i.html", id);

    temp_fd = open (tempfilename, O_CREAT | O_RDWR | O_TRUNC, S_IRWXU);

    // if server sent only header: read further response & dump in a loop

    webpage_size = 0; // Initialize page size to 0

    if (body-buf >= nread) {

        do {

            if ((nread = read(sckt, buf, BUFLEN)) < 0)

                perror("read"), exit(1);

            else if (nread == 0) break;

            if (nread >= BUFLEN)

                fprintf(stderr, "web: need bigger (HTTP) read buffer "), exit(1);

            if (write(temp_fd, buf, nread) != nread)

                perror("file write"), exit(1);

            webpage_size += nread; // Accumulate page size.

        } while (nread > 0);

        close(temp_fd);

    }

    // if server sent header & some body: assume it's the whole page & dump it into file

    else {

        webpage_size = strlen(body);

        if (write(temp_fd, body, strlen(body)) != strlen(body))

            perror("file write"), exit(1);

        close(temp_fd);

    }

     

    // Print out size of webpage content

    printf ("Webpage size %i ", webpage_size);

    // Fork off process to display webpage.

    /* pid = fork ();

    printf ("Process id %i ", pid);

    if (pid == 0) {

        // Run Lynx

        if (execl("/opt/gnu/bin/lynx", "/opt/gnu/bin/lynx", tempfilename, NULL) < 0)

            perror("execl"), exit(1);

        // Better to run netscape if possible

        //if (execl("/usr/local/bin/netscape", "/usr/local/bin/netscape", tempfilename, NULL) < 0)

        // perror("execl"), exit(1);

    }

    else {

        printf ("After forking child process, parent process will now start writing to the file descriptor (pipe or file). ");

    } */

}

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