Answered! Hello, please help me with my systems assignment using c! The code looks quite long but he adds a…

Hello, please help me with my systems assignment using c! The code looks quite long but he adds a lot of fluff, the amount of coding is minimal. Please finish the two “Your Code Here” sections within theserver_getFileByFirstLetter.c program. Thank you so much!

Purpose:

To practice:

Sockets

Low-level I/O in C

Processes and signalling

Assignment:

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 directoryn”,

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 filen”,

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 n”,

returns NULL.

Prints its id and “id num: Sending , bytesn”

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.

Code:

/*-------------------------------------------------------------------------*
 *---                                                                   ---*
 *---           getFileByFirstLetter.h                                  ---*
 *---                                                                   ---*
 *---       This file declares constants common to both the client and
 *---   server of an application where the client asks the user for a   ---*
 *---   letter, and then asks a server for the text of a file that      ---*
 *---   begins with that letter.                                        ---*
 *---                                                                   ---*
 *---   ----    ----    ----    ----    ----    ----    ----    ----    ---*
 *---                                                                   ---*
 *---   Version 1.0             2017 May 14             Joseph Phillips ---*
 *---                                                                   ---*
 *-------------------------------------------------------------------------*/


/*---           Header file inclusion                                   ---*/

#include        
#include        
#include        
#include            // For socket()
#include            // For sockaddr_in and htons()
#include         // For getaddrinfo()
#include         // For errno var
#include              // For open(), read(),write(), stat()
#include         // and close()
#include                // For MacOS()


/*---           Definition of constants:                                ---*/

#define         BUFFER_LEN              256
#define         NO_MATCH_CODE           ((uint32_t) -1)
#define         CANT_READ_FILE_CODE     ((uint32_t) -2)
#define         CANT_READ_DIR_CODE      ((uint32_t) -3)
#define         DEFAULT_HOSTNAME        "localhost"



/*-------------------------------------------------------------------------*
 *---                                                                   ---*
 *---           client_getFileByFirstLetter.c                           ---*
 *---                                                                   ---*
 *---       This file defines a C program that asks the user for a      ---*
 *---   letter, and then asks a server for the text of a file that      ---*
 *---   begins with that letter.                                        ---*
 *---                                                                   ---*
 *---   ----    ----    ----    ----    ----    ----    ----    ----    ---*
 *---                                                                   ---*
 *---   Version 1.0             2017 May 13             Joseph Phillips ---*
 *---                                                                   ---*
 *-------------------------------------------------------------------------*/

/*---           Header file inclusion                                   ---*/

#include        "getFileByFirstLetter.h"
#include         // isalpha()



//  PURPOSE:  To ask the user for the name and the port of the server.  The
//      server name is returned in 'url' up to length 'urlLen'.  The port
//      number is returned in '*portPtr'.  No return value.
void    obtainUrlAndPort        (int            urlLen,
                                 char*          url,
                                 int*           portPtr
                                )
{
  //  I.  Application validity check:
  if  ( (url == NULL)  ||  (portPtr == NULL) )
  {
    fprintf(stderr,"BUG: NULL ptr to obtainUrlAndPort()n");
    exit(EXIT_FAILURE);
  }

  if   (urlLen <= 1)
  {
    fprintf(stderr,"BUG: Bad string length to obtainUrlAndPort()n");
    exit(EXIT_FAILURE);
  }

  //  II.  Get server name and port number:
  //  II.A.  Get server name:
  printf("Machine name [%s]? ",DEFAULT_HOSTNAME);
  fgets(url,urlLen,stdin);

  char* cPtr    = strchr(url,'n');

  if  (cPtr != NULL)
    *cPtr = '';

  if  (url[0] == '')
    strncpy(url,DEFAULT_HOSTNAME,urlLen);

  //  II.B.  Get port numbe:
  char  buffer[BUFFER_LEN];

  printf("Port number? ");
  fgets(buffer,BUFFER_LEN,stdin);

  *portPtr = strtol(buffer,NULL,10);

  //  III.  Finished:
}


//  PURPOSE:  To attempt to connect to the server named 'url' at port 'port'.
//      Returns file-descriptor of socket if successful, or '-1' otherwise.
int     attemptToConnectToServer        (const char*    url,
                                         int            port
                                        )
{
  //  I.  Application validity check:
  if  (url == NULL)
  {
    fprintf(stderr,"BUG: NULL ptr to attemptToConnectToServer()n");
    exit(EXIT_FAILURE);
  }


  //  II.  Attempt to connect to server:
  //  II.A.  Create a socket:
  int socketDescriptor = socket(AF_INET, // AF_INET domain
                                SOCK_STREAM, // Reliable TCP
                                0);

  //  II.B.  Ask DNS about 'url':
  struct addrinfo* hostPtr;
  int status = getaddrinfo(url,NULL,NULL,&hostPtr);

  if (status != 0)
  {
    fprintf(stderr,gai_strerror(status));
    return(-1);
  }

  //  II.C.  Attempt to connect to server:
  struct sockaddr_in server;
  // Clear server datastruct
  memset(&server, 0, sizeof(server));

  // Use TCP/IP
  server.sin_family = AF_INET;

  // Tell port # in proper network byte order
  server.sin_port = htons(port);

  // Copy connectivity info from info on server ("hostPtr")
  server.sin_addr.s_addr =
        ((struct sockaddr_in*)hostPtr->ai_addr)->sin_addr.s_addr;

  status = connect(socketDescriptor,(struct sockaddr*)&server,sizeof(server));

  if  (status < 0)
  {
    fprintf(stderr,"Could not connect %s:%dn",url,port);
    return(-1);
  }

  //  III.  Finished:
  return(socketDescriptor);
}


//  PURPOSE:  To do the work of the application.  Gets letter from user, sends
//      it to server over file-descriptor 'fd', and either prints text of
//      returned error code, or prints returned file.  No return value.
void    communicateWithServer   (int    fd
                                )
{
  //  I.  Application validity check:

  //  II.  Do work of application:
  //  II.A.  Get letter from user:
  char  buffer[BUFFER_LEN+1];

  do
  {
    printf("Please enter a letter to look for: ");
    fgets(buffer,BUFFER_LEN,stdin);
  }
  while  ( !isalpha(buffer[0]) );

  //  II.B.  Send letter to server:
  write(fd,buffer,1);

  //  II.C.  Get response from server:
  uint32_t      fileSize;

  read(fd,&fileSize,sizeof(fileSize));
  fileSize = ntohl(fileSize);

  //  II.D.  Interpret server response:
  switch  (fileSize)
  {
  case NO_MATCH_CODE :
    printf("No matching file found for %cn",buffer[0]);
    break;

  case CANT_READ_FILE_CODE :
    printf("Matching file found for %c, but could not openn",buffer[0]);
    break;

  case CANT_READ_DIR_CODE :
    printf("Server could not open %c.n",buffer[0]);
    break;

  default :
    {
      unsigned int      totalNumBytesRead       = 0;
      int               numBytesRead;

      printf("The file that matches %c has size %un",buffer[0],fileSize);

      while  ( (totalNumBytesRead < fileSize)                        &&
               ( (numBytesRead = read(fd,buffer,BUFFER_LEN)) > 0)
             )
      {
        buffer[numBytesRead]     = '';
        printf("%s",buffer);
        totalNumBytesRead       += (unsigned int)numBytesRead;
      }
    }
  }

  //  III.  Finished:
}


//  PURPOSE:  To do the work of the client.  Ignores command line parameters.
//      Returns 'EXIT_SUCCESS' to OS on success or 'EXIT_FAILURE' otherwise.
int     main    ()
{
  char          url[BUFFER_LEN];
  int           port;
  int           fd;

  obtainUrlAndPort(BUFFER_LEN,url,&port);
  fd    = attemptToConnectToServer(url,port);

  if  (fd < 0)
    exit(EXIT_FAILURE);

  communicateWithServer(fd);
  close(fd);
  return(EXIT_SUCCESS);
}


/*-------------------------------------------------------------------------*
 *---                                                                   ---*
 *---           server_getFileByFirstLetter.c                           ---*
 *---                                                                   ---*
 *---       This file defines a C program that waits for a client to    ---*
 *---   connect, gets a letter from the client, and looks for a file in ---*
 *---   the current directory that begins with that letter.  If it      ---*
 *---   finds such a file then it sends the length of the file back as  ---*
 *---   a network-endian 32-bit unsigned integer, followed by the text  ---*
 *---   of the file.  Sends back the appropriate error integer code     ---*
 *---   otherwise.
 *---                                                                   ---*
 *---   ----    ----    ----    ----    ----    ----    ----    ----    ---*
 *---                                                                   ---*
 *---   Version 2.0             2017 May 19             Joseph Phillips ---*
 *---                                                                   ---*
 *-------------------------------------------------------------------------*/

//
//      Compile with:
//      $ gcc server_getFileByFirstLetter.c -o server -lpthread
//

/*---           Header file inclusion                                   ---*/

#include        "getFileByFirstLetter.h"
#include                        // For opendir(), readdir(), closedir()
#include                       // 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;


//  PURPOSE:  To attempt to create and return a file-descriptor for listening
//      to the OS telling this server when a client process has connect()-ed
//      to 'port'.  Returns that file-descriptor, or 'ERROR_FD' on failure.
int             getServerFileDescriptor
                                (int            port,
                                 const char*    progName
                                )
{
  //  I.  Application validity check:
  if  (progName == NULL)
  {
    fprintf(stderr,"BUG: NULL ptr to getServerFileDescriptor().n");
    exit(EXIT_FAILURE);
  }

  //  II.  Attempt to get socket file descriptor and bind it to 'port':
  //  II.A.  Create a socket
  int socketDescriptor = socket(AF_INET, // AF_INET domain
                                SOCK_STREAM, // Reliable TCP
                                0);

  if  (socketDescriptor < 0)
  {
    perror(progName);
    return(ERROR_FD);
  }

  //  II.B.  Attempt to bind 'socketDescriptor' to 'port':
  //  II.B.1.  We'll fill in this datastruct
  struct sockaddr_in socketInfo;

  //  II.B.2.  Fill socketInfo with 0's
  memset(&socketInfo,'',sizeof(socketInfo));

  //  II.B.3.  Use TCP/IP:
  socketInfo.sin_family = AF_INET;

  //  II.B.4.  Tell port in network endian with htons()
  socketInfo.sin_port = htons(port);

  //  II.B.5.  Allow machine to connect to this service
  socketInfo.sin_addr.s_addr = INADDR_ANY;

  //  II.B.6.  Try to bind socket with port and other specifications
  int status = bind(socketDescriptor, // from socket()
                    (struct sockaddr*)&socketInfo,
                    sizeof(socketInfo)
                   );

  if  (status < 0)
  {
    perror(progName);
    return(ERROR_FD);
  }

  //  II.B.6.  Set OS queue length:
  listen(socketDescriptor,5);

  //  III.  Finished:
  return(socketDescriptor);
}


//  PURPOSE:  To ask the user which port to attempt to monopolize, and to return
//      entered port number.
int             getPort         ()
{
  //  I.  Application validity check:

  //  II.  Get port number
  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) );

  //  III.  Finished:
  return(port);
}



//  PURPOSE:  To do the work of handling the client.  Communication with the
//      client take place using file-descriptor pointed to by '*vPtr'.  Returns
//      'NULL'.
void*           handleClient    (void*  vPtr
                                )
{
  //  I.  Application validity check:

  //  II.  Handle the client:
  //  YOUR CODE HERE

  //  III.  Finished:
  return(NULL);
}


//  PURPOSE:  To serve the clients using file-descriptor 'listenFd' to tell
//      when a client has connected.  Each client is handled by its own child
//      process.  Both the parent and the child processes close unnecesary
//      file-descriptorors.  Serves 'NUM_CLIENTS_TO_SERVE' clients, then quits.
//      No return value.
void            doServer        (int            listenFd
                                )
{
  //  I.  Application validity check:
  if  (listenFd < 0)
  {
    fprintf(stderr,"Illegal file-descriptor to doServer()n");
    exit(EXIT_FAILURE);
  }

  //  II.  Do the work of the server:
  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++)
  {
    //  YOUR CODE HERE
  }

  pthread_join(tId,NULL);
  pthread_attr_destroy(&tAttr);

  //  III.  Finished:
}


//  PURPOSE:  To oversee the main work of the server.  Ignores 'argc' but
//      uses 'argv[0]' as the name of the program.  Returns 'EXIT_SUCCESS' to
//      OS on success or 'EXIT_FAILURE' otherwise.
int             main            (int            argc,
                                 char*          argv[]
                                )
{
  //  I.  Application validity check:

  //  II.  Do server:
  int   port            = getPort();
  int   socketFd        = getServerFileDescriptor(port,argv[0]);

  doServer(socketFd);

  //  III.  Finished:
  return(EXIT_SUCCESS);
}
  

Sample output:

To properly test this program I made a directory called Dir:

$ mkdir Dir
    

I also made a file that I did have permission to read called holdYourHeadUp.txt, and one that I did not called youCantOpenMe.txt. The contents of the second file can be whatever you want, but to make it so you cannot open it say:

$ touch youCantOpenMe.txt 
$ chmod a-rwx youCantOpenMe.txt 
    

My directory now has:

$ ls
20167-3Spr_CSC407-Assign4.html  holdYourHeadUp.txt
client                          server
client_getFileByFirstLetter.c   server_getFileByFirstLetter.c
Dir                             youCantOpenMe.txt
getFileByFirstLetter.h
    
Client output: Server output:
 
$ ./server 
Please enter port number to monopolize [1025-65535]: 2000
        
$ ./client 
Machine name [localhost]? (I just pressed enter) 
Port number? 2000
Please enter a letter to look for: A
No matching file found for A
        
No file begins with A:

0: No matching file
        
$ ./client 
Machine name [localhost]? (I just pressed enter) 
Port number? 2000
Please enter a letter to look for: D
No matching file found for D
        
Dir begins with D, but it is not a file.

1: No matching file
        
$ ./client 
Machine name [localhost]? (I just pressed enter) 
Port number? 2000
Please enter a letter to look for: y
Matching file found for y, but could not open
        
The server cannot open youCantOpenMe.txt.

2: Cannot read file youCantOpenMe.txt
        
$ ./client 
Machine name [localhost]? (I just pressed enter) 
Port number? 2000
Please enter a letter to look for: h
The file that matches h has size 437
And if it's bad
Don't let it get you down, you can take it
And if it hurts
Don't let them see you cry, you can make it

Hold your head up, woman
Hold your head up, woman
Hold your head up, woman
Hold your head high
Hold your head up, woman
Hold your head up, woman
Hold your head up, woman
Hold your head high

And if they stare
Just let them burn their eyes on you moving
And if they shout
Don't let it change a thing that you're doing
        
The server can open holdYourHeadUp.txt, so it sends it to the client.

3: Sending holdYourHeadUp.txt, 437 bytes
And if it's bad
Don't let it get you down, you can take it
And if it hurts
Don't let them see you cry, you can make it

Hold your head up, woman
Hold your head up, woman
Hold your head up, woman
Hold your head high
Hold your head up, woman
Hold your head up, woman
Hold your head up, woman
Hold your head high

And if they stare
Just let them burn their eyes on you moving
And if they shout
Don't let it change a thing that you're doing
        

Expert Answer

 /*— Header file inclusion —*/
  • #include        
    #include        
    #include        
    #include            // For socket()
    #include            // For sockaddr_in and htons()
    #include         // For getaddrinfo()
    #include         // For errno var
    #include              // For open(), read(),write(), stat()
    #include         // and close()
    #include                // For MacOS()
    
    
    /*---           Definition of constants:                                ---*/
    
    #define         BUFFER_LEN              256
    #define         NO_MATCH_CODE           ((uint32_t) -1)
    #define         CANT_READ_FILE_CODE     ((uint32_t) -2)
    #define         CANT_READ_DIR_CODE      ((uint32_t) -3)
    #define         DEFAULT_HOSTNAME        "localhost"
    
    
    
    /*-------------------------------------------------------------------------*
     *---                                                                   ---*
     *---           client_getFileByFirstLetter.c                           ---*
     *---                                                                   ---*
     *---       This file defines a C program that asks the user for a      ---*
     *---   letter, and then asks a server for the text of a file that      ---*
     *---   begins with that letter.                                        ---*
     *---                                                                   ---*
     *---   ----    ----    ----    ----    ----    ----    ----    ----    ---*
     *---                                                                   ---*
     *---   Version 1.0             2017 May 13             Joseph Phillips ---*
     *---                                                                   ---*
     *-------------------------------------------------------------------------*/
    
    /*---           Header file inclusion                                   ---*/
    
    #include        "getFileByFirstLetter.h"
    #include         // isalpha()
    
    
    
    //  PURPOSE:  To ask the user for the name and the port of the server.  The
    //      server name is returned in 'url' up to length 'urlLen'.  The port
    //      number is returned in '*portPtr'.  No return value.
    void    obtainUrlAndPort        (int            urlLen,
                                     char*          url,
                                     int*           portPtr
                                    )
    {
      //  I.  Application validity check:
      if  ( (url == NULL)  ||  (portPtr == NULL) )
      {
        fprintf(stderr,"BUG: NULL ptr to obtainUrlAndPort()n");
        exit(EXIT_FAILURE);
      }
    
      if   (urlLen <= 1)
      {
        fprintf(stderr,"BUG: Bad string length to obtainUrlAndPort()n");
        exit(EXIT_FAILURE);
      }
    
      //  II.  Get server name and port number:
      //  II.A.  Get server name:
      printf("Machine name [%s]? ",DEFAULT_HOSTNAME);
      fgets(url,urlLen,stdin);
    
      char* cPtr    = strchr(url,'n');
    
      if  (cPtr != NULL)
        *cPtr = '';
    
      if  (url[0] == '')
        strncpy(url,DEFAULT_HOSTNAME,urlLen);
    
      //  II.B.  Get port numbe:
      char  buffer[BUFFER_LEN];
    
      printf("Port number? ");
      fgets(buffer,BUFFER_LEN,stdin);
    
      *portPtr = strtol(buffer,NULL,10);
    
      //  III.  Finished:
    }
    
    
    //  PURPOSE:  To attempt to connect to the server named 'url' at port 'port'.
    //      Returns file-descriptor of socket if successful, or '-1' otherwise.
    int     attemptToConnectToServer        (const char*    url,
                                             int            port
                                            )
    {
      //  I.  Application validity check:
      if  (url == NULL)
      {
        fprintf(stderr,"BUG: NULL ptr to attemptToConnectToServer()n");
        exit(EXIT_FAILURE);
      }
    
    
      //  II.  Attempt to connect to server:
      //  II.A.  Create a socket:
      int socketDescriptor = socket(AF_INET, // AF_INET domain
                                    SOCK_STREAM, // Reliable TCP
                                    0);
    
      //  II.B.  Ask DNS about 'url':
      struct addrinfo* hostPtr;
      int status = getaddrinfo(url,NULL,NULL,&hostPtr);
    
      if (status != 0)
      {
        fprintf(stderr,gai_strerror(status));
        return(-1);
      }
    
      //  II.C.  Attempt to connect to server:
      struct sockaddr_in server;
      // Clear server datastruct
      memset(&server, 0, sizeof(server));
    
      // Use TCP/IP
      server.sin_family = AF_INET;
    
      // Tell port # in proper network byte order
      server.sin_port = htons(port);
    
      // Copy connectivity info from info on server ("hostPtr")
      server.sin_addr.s_addr =
            ((struct sockaddr_in*)hostPtr->ai_addr)->sin_addr.s_addr;
    
      status = connect(socketDescriptor,(struct sockaddr*)&server,sizeof(server));
    
      if  (status < 0)
      {
        fprintf(stderr,"Could not connect %s:%dn",url,port);
        return(-1);
      }
    
      //  III.  Finished:
      return(socketDescriptor);
    }
    
    
    //  PURPOSE:  To do the work of the application.  Gets letter from user, sends
    //      it to server over file-descriptor 'fd', and either prints text of
    //      returned error code, or prints returned file.  No return value.
    void    communicateWithServer   (int    fd
                                    )
    {
      //  I.  Application validity check:
    
      //  II.  Do work of application:
      //  II.A.  Get letter from user:
      char  buffer[BUFFER_LEN+1];
    
      do
      {
        printf("Please enter a letter to look for: ");
        fgets(buffer,BUFFER_LEN,stdin);
      }
      while  ( !isalpha(buffer[0]) );
    
      //  II.B.  Send letter to server:
      write(fd,buffer,1);
    
      //  II.C.  Get response from server:
      uint32_t      fileSize;
    
      read(fd,&fileSize,sizeof(fileSize));
      fileSize = ntohl(fileSize);
    
      //  II.D.  Interpret server response:
      switch  (fileSize)
      {
      case NO_MATCH_CODE :
        printf("No matching file found for %cn",buffer[0]);
        break;
    
      case CANT_READ_FILE_CODE :
        printf("Matching file found for %c, but could not openn",buffer[0]);
        break;
    
      case CANT_READ_DIR_CODE :
        printf("Server could not open %c.n",buffer[0]);
        break;
    
      default :
        {
          unsigned int      totalNumBytesRead       = 0;
          int               numBytesRead;
    
          printf("The file that matches %c has size %un",buffer[0],fileSize);
    
          while  ( (totalNumBytesRead < fileSize)                        &&
                   ( (numBytesRead = read(fd,buffer,BUFFER_LEN)) > 0)
                 )
          {
            buffer[numBytesRead]     = '';
            printf("%s",buffer);
            totalNumBytesRead       += (unsigned int)numBytesRead;
          }
        }
      }
    
      //  III.  Finished:
    }
    
    
    //  PURPOSE:  To do the work of the client.  Ignores command line parameters.
    //      Returns 'EXIT_SUCCESS' to OS on success or 'EXIT_FAILURE' otherwise.
    int     main    ()
    {
      char          url[BUFFER_LEN];
      int           port;
      int           fd;
    
      obtainUrlAndPort(BUFFER_LEN,url,&port);
      fd    = attemptToConnectToServer(url,port);
    
      if  (fd < 0)
        exit(EXIT_FAILURE);
    
      communicateWithServer(fd);
      close(fd);
      return(EXIT_SUCCESS);
    }
    
    
    /*-------------------------------------------------------------------------*
     *---                                                                   ---*
     *---           server_getFileByFirstLetter.c                           ---*
     *---                                                                   ---*
     *---       This file defines a C program that waits for a client to    ---*
     *---   connect, gets a letter from the client, and looks for a file in ---*
     *---   the current directory that begins with that letter.  If it      ---*
     *---   finds such a file then it sends the length of the file back as  ---*
     *---   a network-endian 32-bit unsigned integer, followed by the text  ---*
     *---   of the file.  Sends back the appropriate error integer code     ---*
     *---   otherwise.
     *---                                                                   ---*
     *---   ----    ----    ----    ----    ----    ----    ----    ----    ---*
     *---                                                                   ---*
     *---   Version 2.0             2017 May 19             Joseph Phillips ---*
     *---                                                                   ---*
     *-------------------------------------------------------------------------*/
    
    //
    //      Compile with:
    //      $ gcc server_getFileByFirstLetter.c -o server -lpthread
    //
    
    /*---           Header file inclusion                                   ---*/
    
    #include        "getFileByFirstLetter.h"
    #include                        // For opendir(), readdir(), closedir()
    #include                       // 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;
    
    
    //  PURPOSE:  To attempt to create and return a file-descriptor for listening
    //      to the OS telling this server when a client process has connect()-ed
    //      to 'port'.  Returns that file-descriptor, or 'ERROR_FD' on failure.
    int             getServerFileDescriptor
                                    (int            port,
                                     const char*    progName
                                    )
    {
      //  I.  Application validity check:
      if  (progName == NULL)
      {
        fprintf(stderr,"BUG: NULL ptr to getServerFileDescriptor().n");
        exit(EXIT_FAILURE);
      }
    
      //  II.  Attempt to get socket file descriptor and bind it to 'port':
      //  II.A.  Create a socket
      int socketDescriptor = socket(AF_INET, // AF_INET domain
                                    SOCK_STREAM, // Reliable TCP
                                    0);
    
      if  (socketDescriptor < 0)
      {
        perror(progName);
        return(ERROR_FD);
      }
    
      //  II.B.  Attempt to bind 'socketDescriptor' to 'port':
      //  II.B.1.  We'll fill in this datastruct
      struct sockaddr_in socketInfo;
    
      //  II.B.2.  Fill socketInfo with 0's
      memset(&socketInfo,'',sizeof(socketInfo));
    
      //  II.B.3.  Use TCP/IP:
      socketInfo.sin_family = AF_INET;
    
      //  II.B.4.  Tell port in network endian with htons()
      socketInfo.sin_port = htons(port);
    
      //  II.B.5.  Allow machine to connect to this service
      socketInfo.sin_addr.s_addr = INADDR_ANY;
    
      //  II.B.6.  Try to bind socket with port and other specifications
      int status = bind(socketDescriptor, // from socket()
                        (struct sockaddr*)&socketInfo,
                        sizeof(socketInfo)
                       );
    
      if  (status < 0)
      {
        perror(progName);
        return(ERROR_FD);
      }
    
      //  II.B.6.  Set OS queue length:
      listen(socketDescriptor,5);
    
      //  III.  Finished:
      return(socketDescriptor);
    }
    
    
    //  PURPOSE:  To ask the user which port to attempt to monopolize, and to return
    //      entered port number.
    int             getPort         ()
    {
      //  I.  Application validity check:
    
      //  II.  Get port number
      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) );
    
      //  III.  Finished:
      return(port);
    }
    
    
    
    //  PURPOSE:  To do the work of handling the client.  Communication with the
    //      client take place using file-descriptor pointed to by '*vPtr'.  Returns
    //      'NULL'.
    void*           handleClient    (void*  vPtr
                                    )
    {
      //  I.  Application validity check:
    
      //  II.  Handle the client:
      //  YOUR CODE HERE
    
      //  III.  Finished:
      return(NULL);
    }
    
    
    //  PURPOSE:  To serve the clients using file-descriptor 'listenFd' to tell
    //      when a client has connected.  Each client is handled by its own child
    //      process.  Both the parent and the child processes close unnecesary
    //      file-descriptorors.  Serves 'NUM_CLIENTS_TO_SERVE' clients, then quits.
    //      No return value.
    void            doServer        (int            listenFd
                                    )
    {
      //  I.  Application validity check:
      if  (listenFd < 0)
      {
        fprintf(stderr,"Illegal file-descriptor to doServer()n");
        exit(EXIT_FAILURE);
      }
    
      //  II.  Do the work of the server:
      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++)
      {
        //  YOUR CODE HERE
      }
    
      pthread_join(tId,NULL);
      pthread_attr_destroy(&tAttr);
    
      //  III.  Finished:
    }
    
    
    //  PURPOSE:  To oversee the main work of the server.  Ignores 'argc' but
    //      uses 'argv[0]' as the name of the program.  Returns 'EXIT_SUCCESS' to
    //      OS on success or 'EXIT_FAILURE' otherwise.
    int             main            (int            argc,
                                     char*          argv[]
                                    )
    {
      //  I.  Application validity check:
    
      //  II.  Do server:
      int   port            = getPort();
      int   socketFd        = getServerFileDescriptor(port,argv[0]);
    
      doServer(socketFd);
    
      //  III.  Finished:
      return(EXIT_SUCCESS);
    }
Still stressed from student homework?
Get quality assistance from academic writers!