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

Please finish the server of a client-server application. The client asks the use

ID: 3842435 • Letter: P

Question

Please finish the server of a client-server application. The client asks the user for a letter (a character in {A-Z,a-z}), and then sends that letter to the server. The server malloc()s memory to store both the loop variable i and the file descriptor from accept() for talking to the client. It then pthread_create()s a child to handle the client and gives it the malloc()ed memory. All of the threads except the last (i == (NUM_CLIENTS_TO_SERVE-1)) should be detached threads. The last thread should be an ordinary, joinable thread, which the parent thread should join with outside the loop.

The child thread should:

Get the thread id (coming in as the loop variable) and file descriptor. It then free()s that malloc()ed memory.

Gets the letter from the client

Attempts to open the current directory ("."). If it cannot open that directory then it:

sends CANT_READ_DIR_CODE back to the client (in network endian),

prints its id and "id num: Cannot read directory ",

returns NULL.

Iterates thru the directory to looking for a file (not a directory or anything else) whose name starts with the letter obtained from the client.

If the server finds no matching file then it

sends NO_MATCH_CODE back to the client (in network endian),

prints its id and "id num: No matching file ",

returns NULL.

Attempts to open the file for reading. If it cannot open the file then it:

sends CANT_READ_FILE_CODE back to the client (in network endian),

prints its id and "id num: Cannot read file <filename> ",

returns NULL.

Prints its id and "id num: Sending <filename>, <numBytes> bytes "

Sends the size of the file as a uint32_t integer to the client (in network endian)

Sends the bytes of the file to the client. It should send the file in buffers of bytes of size BUFFER_LEN.

close()s what it should close.

returns NULL.

Explanation / Answer

#include        "getFileByFirstLetter.h"

#include        <dirent.h>                // For opendir(), readdir(), closedir()

#include        <pthread.h>               // For pthread_create(), etc.

const int       LO_LEGAL_PORT           = 1025;

const int       HI_LEGAL_PORT           = 65535;

const int       ERROR_FD                = -1;

const int       NUM_CLIENTS_TO_SERVE    = 4;

int   getServerFileDescriptor

(int port,const char*    progName)

{

if (progName == NULL)

{

fprintf(stderr,"BUG: NULL ptr to getServerFileDescriptor(). ");

exit(EXIT_FAILURE);

}

int socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);

if (socketDescriptor < 0)

{

    perror(progName);

    return(ERROR_FD);

}

struct sockaddr_in socketInfo;

memset(&socketInfo,'',sizeof(socketInfo));

socketInfo.sin_family = AF_INET;

socketInfo.sin_port = htons(port);

socketInfo.sin_addr.s_addr = INADDR_ANY;

int status = bind(socketDescriptor, // from socket()

                    (struct sockaddr*)&socketInfo,

                    sizeof(socketInfo)

                   );

if (status < 0)

{

    perror(progName);

    return(ERROR_FD);

}

listen(socketDescriptor,5);

return(socketDescriptor);

}

int             getPort         ()

{

int   port;

do

{

    char        buffer[BUFFER_LEN];

    printf("Please enter port number to monopolize [%d-%d]: ",

           LO_LEGAL_PORT,HI_LEGAL_PORT

          );

    fgets(buffer,BUFFER_LEN,stdin);

    port = strtol(buffer,NULL,10);

}

while ( (port < LO_LEGAL_PORT) || (port > HI_LEGAL_PORT) );

return(port);

}

void*           handleClient    (void* vPtr

                                )

{

return(NULL);

}

void            doServer        (int            listenFd

                                )

{

if (listenFd < 0)

{

    fprintf(stderr,"Illegal file-descriptor to doServer() ");

    exit(EXIT_FAILURE);

}

int                   i;

pthread_t             tId;

pthread_attr_t        tAttr;

pthread_attr_init(&tAttr);

pthread_attr_setdetachstate(&tAttr,PTHREAD_CREATE_DETACHED);

for (i = 0; i < NUM_CLIENTS_TO_SERVE; i++)

{ }

pthread_join(tId,NULL);

pthread_attr_destroy(&tAttr);

}

int main (int argc char* argv[])

{

int port = getPort();

int   socketFd= getServerFileDescriptor(port,argv[0]);

doServer(socketFd);

return(EXIT_SUCCESS);

}