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

What is wrong with this code? I cannot get the port to connect to the socket at

ID: 3862752 • Letter: W

Question

What is wrong with this code? I cannot get the port to connect to the socket at all. When I enter a port number the client does nothing.

Instructions:

Implementing doServer(int listenFd) (10 Points):

doServer() should have a loop in which it waits for a client to connect to listenFd. When a client does, it should:

malloc() enough memory for 2 integers

put the file descriptor from accept() in one of those spaces

put the value of threadCount in the other space, and increment threadCount

Make a detached thread to handle this new client. I called my function handleClient(), but you may call yours whatever. Pass the address of your malloc()-ed array.

The loop should then go back for another accept().

void* handleClient(void* vPtr) (10 Points):

(Or whatever you call your function that runs a thread for the client.)The thread id and the file descriptor are passed, but they come in as a void* pointer.

Use another pointer to cast back to int*

Save the file descriptor and thread number in local vars

free() the memory

Print the thread number and do a loop like this:

It read()s a line of text from the client into buffer[], and parses the line into a command character, fileNum integer, and quote-delineated text[] string. (The fileNum and text[] may or may not be given, depending upon the value of command.)

Then do the following operations based upon the value of command. Except for QUIT_CMD_CHAR I strongly recommend using a different function for each!

When the function ends just have it do:

command == DIR_CMD_CHAR (15 Points):

Open the current directory (named "."). If an error occurs then just send STD_ERROR_MSG back to the client.

Copy as many entries that will fit into a buffer of length BUFFER_LEN. Be sure to put a separating ' ' after each entry.

Close the directory.

command == READ_CMD_CHAR (15 Points):

Open the file with the number fileNum. Get the name from the number with:

read() up to BUFFER_LEN into a buffer. Put a '' character at the end of the buffer.

Send that buffer to the client.

Close the file.

If an error occurs during any of this, then send STD_ERROR_MSG back to the client.

command == WRITE_CMD_CHAR (15 Points):

The opposite of READ_CMD_CHAR. fileNum and text have the file number and text respectively from the client. Save that text to the named file. If there is an error send then send STD_ERROR_MSG back to the client. If you succeeded then send STD_OKAY_MSG back to the client.

command == DELETE_CMD_CHAR (10 Points):

fileNum tells the file number of the file to delete. Using the unlink() command. If there is an error send then send STD_ERROR_MSGback to the client. If you succeeded then send STD_OKAY_MSG back to the client.

command == CALC_CMD_CHAR (15 Points):

fork() a child. If fork() fails then send STD_ERROR_MSG back to the client.

For the child, do the following:

Then run CALC_PROGNAME. If running that fails, then do:

For the parent wait() for the child. If the child crashed or did not return EXIT_SUCCESS then send STD_ERROR_MSG back to the client.

If the child did not crash and returned EXIT_SUCCESS, then read() the first BUFFER_LEN chars from the file named OUTPUT_FILENAME. If there is any more space left in your buffer, then read() from the file named ERROR_FILENAME into the same buffer so that it has BUFFER_LEN chars maximum.

close() both files.

Send your buffer back to the client.

command == QUIT_CMD_CHAR (10 Points):

Just send STD_BYE_MSG back to the client and set shouldContinue to 0 to quit the loop.

/*-------------------------------------------------------------------------*
*---                                   ---*
*---       mathServer.c                       ---*
*---                                   ---*
*---   This file defines a C program that gets file-sys commands   ---*
*---   from client via a socket, executes those commands in their own   ---*
*---   threads, and returns the corresponding output back to the   ---*
*---   client.                               ---*
*---                                   ---*
*---   ----   ----   ----   ----   ----   ----   ----   ----   ---*
*---                                   ---*
*---   Version 1.0       2017 February 20   Joseph Phillips   ---*
*---                                   ---*
*-------------------------------------------------------------------------*/

//   Compile with:
//   $ gcc mathServer.c -o mathServer -lpthread

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

#include   "mathClientServer.h"
#include   <errno.h>   // For perror()
#include   <pthread.h>   // For pthread_create()
#include   <string.h>
#include <sys/socket.h>//For socket()
#include <netinet/in.h>//For sockaddr_in and htons()
#include <signal.h>
#include <wait.h>


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

#define       STD_OKAY_MSG       "Okay"

#define       STD_ERROR_MSG       "Error doing operation"

#define       STD_BYE_MSG       "Good bye!"

#define       THIS_PROGRAM_NAME   "mathServer"

#define       FILENAME_EXTENSION   ".bc"

#define       OUTPUT_FILENAME       "out.txt"

#define       ERROR_FILENAME       "err.txt"

#define       CALC_PROGNAME       "/usr/bin/bc"

const int   ERROR_FD       = -1;

extern void* handleClient(void* vPtr);
extern int       getServerFileDescriptor();


//---       Definition of functions:               ---//

// PURPOSE: To run the server by 'accept()'-ing client requests from
//   'listenFd' and doing them.
void       doServer   (int       listenFd)
{
/* Application validity check: */

/* Server clients: */
pthread_t       threadId;
pthread_attr_t   threadAttr;
int           threadCount   = 0;
int *iPtr;

  
/* YOUR CODE HERE: */
while(1)
  
{
/* Accept connection to client: */
int conffd = accept(listenFd, NULL, NULL);
  
/* Malloc memory for two integers: */
iPtr = (int *)calloc(2, sizeof(int));
  
/*Put file descriptor in the first space: */
iPtr[0] = listenFd; // or just listenFd not sure

/* put threadCount into the second space and increment: */
iPtr[1] = threadCount++;

/* Creates detached thread for handleClient and passes the address of iPtr */
pthread_attr_init(&threadAttr);
pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
pthread_create(&threadId, &threadAttr, handleClient, (void*)iPtr);

pthread_join(threadId, NULL);
pthread_attr_destroy(&threadAttr);

  
}
  
  
}
void* handleClient(void* vPtr)
{
/* Read command: */
char   buffer[BUFFER_LEN];
char   command;
int   fileNum;
char   text[BUFFER_LEN];
int    shouldContinue   = 1;
int threadNum;
int fd;
  
/* Cast void* vPtr back to an int */
int *iPtr = (int *)vPtr;
  
/* Assign file descriptor to a local value named 'fd'*/
fd = iPtr[0];
/* Assign thread number to local value named 'threadNum'*/
threadNum = iPtr[1];
  
free(iPtr);
  
while (shouldContinue)
{
memset(buffer,'',BUFFER_LEN);
memset(text ,'',BUFFER_LEN);

read(fd,buffer,BUFFER_LEN);
printf("Thread %d received: %s ",threadNum,buffer);
sscanf(buffer,"%c %d "%[^"]"",&command,&fileNum,text);

/* YOUR CODE HERE: */
  
if(command == DIR_CMD_CHAR)
{
/* 1. Open the current directory (named "."). If an error occurs then just send STD_ERROR_MSG back to the client: */
DIR* dirPtr = opendir(".");
struct dirent* entryPtr;
  
/* If error occurs send STD_ERROR_MSG to client: */
if ((dirPtr = opendir (".")) == NULL) {
{
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
//return(EXIT_FAILURE);
}
  
/* Read as many entries that will fit into BUFFER_LEN
put as many entries into the buffer and send the buffer to client
d_name=entryPtr into the bufffer using strcat_s,
make sure buffer starts empty
buffer[0]=' ';
add new line char using stringcat " "
make sure do not go over buffer lengh */
  
if (dirPtr)
{
while ((entryPtr = readdir(dirPtr)) != NULL)
{
  
buffer[0]='';
  
int i;
int sizebuf = sizeof(buffer);
  
for (i = 0; i < sizebuf; i++)
{
strcat(buffer,entryPtr->d_name);
strcat(buffer," ");
}
}
}
/* 3. Close directory */
closedir(dirPtr);
}
  
  
else if (command == READ_CMD_CHAR)
{
/* 1. Open the file with the number fileNum. Get the name from the number with: */
fileNum = open(FILENAME_EXTENSION,O_RDONLY, 0); //Yeah, I think this is right, except with fileNum instead.
  
// changed fd to fileNum
  
/* If error occurs send STD_ERROR_MSG to client: */
if(fileNum < 0)
{
write(fileNum, STD_ERROR_MSG, sizeof(STD_ERROR_MSG)); // it looks like this is correct

exit(1);
}
  
/* 2. read() up to BUFFER_LEN into a buffer. Put a '' character at the end of the buffer: */
char   fileName[BUFFER_LEN];
snprintf(fileName,BUFFER_LEN,"%d%s",fileNum,FILENAME_EXTENSION);
  
fileNum = read(fileNum, fileName, BUFFER_LEN-1);
  
fileName[fileNum] = '';
printf("Sending: %s", fileName);
write(fileNum, fileName, fileNum);
/* Close file: */
close(fileNum);
  
}

else if (command == WRITE_CMD_CHAR)
{
/* 1. Open the file with the number fileNum in write mode: */
fileNum = open(FILENAME_EXTENSION,O_WRONLY|O_CREAT|O_TRUNC,0660);
  
/* If error occurs send STD_ERROR_MSG to client: */
if(fileNum < 0)
{
write(fileNum, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
}

  
if (fileNum >0)
{
//fileNum and text have the file number and text respectively from the client.
//Save that text to the named file.
char   fileName[BUFFER_LEN];
write (fileNum,fileName, sizeof(fileName));
  
  
//If you succeeded then send STD_OKAY_MSG back to the client
write(fileNum, STD_OKAY_MSG, sizeof(STD_OKAY_MSG));
  
}
  
/* Close file: */
close(fileNum);
}


else if (command == CALC_CMD_CHAR)
{
/* Create new fork named calcPid: */
int calcPid = fork();
  
/* If fork() failed: */
if(calcPid < 0)
{
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
}
/* Child writes files: */
else if(calcPid == 0)
{
char   fileName[BUFFER_LEN];
  
snprintf(fileName,BUFFER_LEN,"%d%s",fileNum,FILENAME_EXTENSION);

int   inFd   = open(fileName,O_RDONLY,0);
int   outFd   = open(OUTPUT_FILENAME,O_WRONLY|O_CREAT|O_TRUNC,0660);
int   errFd   = open(ERROR_FILENAME, O_WRONLY|O_CREAT|O_TRUNC,0660);

if ( (inFd < 0) || (outFd < 0) || (errFd < 0) )
{
fprintf(stderr,"Could not open one or more files ");
exit(EXIT_FAILURE);
}

close(0);
dup(inFd);
close(1);
dup(outFd);
close(2);
dup(errFd);
  
/* Run CALC_PROGNAME, if fails generate output: */
execl(CALC_PROGNAME,CALC_PROGNAME,fileName,NULL);
fprintf(stderr,"Could not execl %s ",CALC_PROGNAME);
exit(EXIT_FAILURE);  

}
/* Parent reads files: */
else
{
  
/* Wait and check status of child process, if it crashes return STD_ERROR_MSG: */
int status;
pid_t return_pid = waitpid(calcPid, &status, WNOHANG);
  
if (return_pid == -1)
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
  
/* If child process EXIT_SUCCESS, then run parent process: */
if (return_pid == calcPid)
{
char   fileName[BUFFER_LEN];
  
snprintf(fileName,BUFFER_LEN,"%d%s",fileNum,FILENAME_EXTENSION);
int numBytes = 0;
  
  
int   outFd   = open(OUTPUT_FILENAME,O_RDONLY|O_CREAT,0660);
int   errFd   = open(ERROR_FILENAME, O_RDONLY|O_CREAT,0660);

if ( (outFd < 0) || (errFd < 0) )
{
fprintf(stderr,"Could not open one or more files ");
exit(EXIT_FAILURE);
}
  
while ( (numBytes = read(outFd, fileName, BUFFER_LEN)) > 0)
read(errFd, &fileName[numBytes], BUFFER_LEN);
  
close(0);
dup(outFd);
close(1);
dup(errFd);
}
}
}
  
else if (command == DELETE_CMD_CHAR)
{
if (fileNum > 0)
{
fileNum = unlink(buffer);
write(fd, STD_OKAY_MSG, sizeof(STD_OKAY_MSG));
}
else
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
}
  
else if (command == QUIT_CMD_CHAR)
{
/* Send STD_BYE_MSG back to the client and set shouldContinue to 0 to quit the loop: */   
write(fd, STD_BYE_MSG, sizeof(STD_BYE_MSG));
shouldContinue = 0;
}
}
  
}
  
  
printf("Thread %d quitting. ",threadNum);
return(NULL);
}


// PURPOSE: To decide a port number, either from the command line arguments
//   'argc' and 'argv[]', or by asking the user. Returns port number.
int       getPortNum   (int   argc,
               char*   argv[]
               )
{
// I. Application validity check:

// II. Get listening socket:
int   portNum;

if (argc >= 2)
portNum   = strtol(argv[1],NULL,0);
else
{
char   buffer[BUFFER_LEN];

printf("Port number to monopolize? ");
fgets(buffer,BUFFER_LEN,stdin);
portNum   = strtol(buffer,NULL,0);
}

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


// 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
               )
{
// I. Application validity check:

// 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(THIS_PROGRAM_NAME);
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(THIS_PROGRAM_NAME);
return(ERROR_FD);
}

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

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


int       main       (int   argc,
               char*   argv[]
               )
{
// I. Application validity check:

// II. Do server:
int    port   = getPortNum(argc,argv);
int   listenFd   = getServerFileDescriptor(port);
int   status   = EXIT_FAILURE;

if (listenFd >= 0)
{
doServer(listenFd);
close(listenFd);
status   = EXIT_SUCCESS;
}

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

Explanation / Answer

//   $ gcc mathServer.c -o mathServer -lpthread

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

#include   "mathClientServer.h"
#include   <errno.h>   // For perror()
#include   <pthread.h>   // For pthread_create()
#include   <string.h>
#include <sys/socket.h>//For socket()
#include <netinet/in.h>//For sockaddr_in and htons()
#include <signal.h>
#include <wait.h>


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

#define       STD_OKAY_MSG       "Okay"

#define       STD_ERROR_MSG       "Error doing operation"

#define       STD_BYE_MSG       "Good bye!"

#define       THIS_PROGRAM_NAME   "mathServer"

#define       FILENAME_EXTENSION   ".bc"

#define       OUTPUT_FILENAME       "out.txt"

#define       ERROR_FILENAME       "err.txt"

#define       CALC_PROGNAME       "/usr/bin/bc"

const int   ERROR_FD       = -1;

extern void* handleClient(void* vPtr);
extern int       getServerFileDescriptor();


//---       Definition of functions:               ---//

// PURPOSE: To run the server by 'accept()'-ing client requests from
//   'listenFd' and doing them.
void       doServer   (int       listenFd)
{
/* Application validity check: */

/* Server clients: */
pthread_t       threadId;
pthread_attr_t   threadAttr;
int           threadCount   = 0;
int *iPtr;

  
/* YOUR CODE HERE: */
while(1)
  
{
/* Accept connection to client: */
int conffd = accept(listenFd, NULL, NULL);
  
/* Malloc memory for two integers: */
iPtr = (int *)calloc(2, sizeof(int));
  
/*Put file descriptor in the first space: */
iPtr[0] = listenFd; // or just listenFd not sure

/* put threadCount into the second space and increment: */
iPtr[1] = threadCount++;

/* Creates detached thread for handleClient and passes the address of iPtr */
pthread_attr_init(&threadAttr);
pthread_attr_setdetachstate(&threadAttr, PTHREAD_CREATE_DETACHED);
pthread_create(&threadId, &threadAttr, handleClient, (void*)iPtr);

pthread_join(threadId, NULL);
pthread_attr_destroy(&threadAttr);

  
}
  
  
}
void* handleClient(void* vPtr)
{
/* Read command: */
char   buffer[BUFFER_LEN];
char   command;
int   fileNum;
char   text[BUFFER_LEN];
int    shouldContinue   = 1;
int threadNum;
int fd;
  
/* Cast void* vPtr back to an int */
int *iPtr = (int *)vPtr;
  
/* Assign file descriptor to a local value named 'fd'*/
fd = iPtr[0];
/* Assign thread number to local value named 'threadNum'*/
threadNum = iPtr[1];
  
free(iPtr);
  
while (shouldContinue)
{
memset(buffer,'',BUFFER_LEN);
memset(text ,'',BUFFER_LEN);

read(fd,buffer,BUFFER_LEN);
printf("Thread %d received: %s ",threadNum,buffer);
sscanf(buffer,"%c %d "%[^"]"",&command,&fileNum,text);

/* YOUR CODE HERE: */
  
if(command == DIR_CMD_CHAR)
{
/* 1. Open the current directory (named "."). If an error occurs then just send STD_ERROR_MSG back to the client: */
DIR* dirPtr = opendir(".");
struct dirent* entryPtr;
  
/* If error occurs send STD_ERROR_MSG to client: */
if ((dirPtr = opendir (".")) == NULL) {
{
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
//return(EXIT_FAILURE);
}
  
/* Read as many entries that will fit into BUFFER_LEN
put as many entries into the buffer and send the buffer to client
d_name=entryPtr into the bufffer using strcat_s,
make sure buffer starts empty
buffer[0]=' ';
add new line char using stringcat " "
make sure do not go over buffer lengh */
  
if (dirPtr)
{
while ((entryPtr = readdir(dirPtr)) != NULL)
{
  
buffer[0]='';
  
int i;
int sizebuf = sizeof(buffer);
  
for (i = 0; i < sizebuf; i++)
{
strcat(buffer,entryPtr->d_name);
strcat(buffer," ");
}
}
}
/* 3. Close directory */
closedir(dirPtr);
}
  
  
else if (command == READ_CMD_CHAR)
{
/* 1. Open the file with the number fileNum. Get the name from the number with: */
fileNum = open(FILENAME_EXTENSION,O_RDONLY, 0); //Yeah, I think this is right, except with fileNum instead.
  
// changed fd to fileNum
  
/* If error occurs send STD_ERROR_MSG to client: */
if(fileNum < 0)
{
write(fileNum, STD_ERROR_MSG, sizeof(STD_ERROR_MSG)); // it looks like this is correct

exit(1);
}
  
/* 2. read() up to BUFFER_LEN into a buffer. Put a '' character at the end of the buffer: */
char   fileName[BUFFER_LEN];
snprintf(fileName,BUFFER_LEN,"%d%s",fileNum,FILENAME_EXTENSION);
  
fileNum = read(fileNum, fileName, BUFFER_LEN-1);
  
fileName[fileNum] = '';
printf("Sending: %s", fileName);
write(fileNum, fileName, fileNum);
/* Close file: */
close(fileNum);
  
}

else if (command == WRITE_CMD_CHAR)
{
/* 1. Open the file with the number fileNum in write mode: */
fileNum = open(FILENAME_EXTENSION,O_WRONLY|O_CREAT|O_TRUNC,0660);
  
/* If error occurs send STD_ERROR_MSG to client: */
if(fileNum < 0)
{
write(fileNum, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
}

  
if (fileNum >0)
{
//fileNum and text have the file number and text respectively from the client.
//Save that text to the named file.
char   fileName[BUFFER_LEN];
write (fileNum,fileName, sizeof(fileName));
  
  
//If you succeeded then send STD_OKAY_MSG back to the client
write(fileNum, STD_OKAY_MSG, sizeof(STD_OKAY_MSG));
  
}
  
/* Close file: */
close(fileNum);
}


else if (command == CALC_CMD_CHAR)
{
/* Create new fork named calcPid: */
int calcPid = fork();
  
/* If fork() failed: */
if(calcPid < 0)
{
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
}
/* Child writes files: */
else if(calcPid == 0)
{
char   fileName[BUFFER_LEN];
  
snprintf(fileName,BUFFER_LEN,"%d%s",fileNum,FILENAME_EXTENSION);

int   inFd   = open(fileName,O_RDONLY,0);
int   outFd   = open(OUTPUT_FILENAME,O_WRONLY|O_CREAT|O_TRUNC,0660);
int   errFd   = open(ERROR_FILENAME, O_WRONLY|O_CREAT|O_TRUNC,0660);

if ( (inFd < 0) || (outFd < 0) || (errFd < 0) )
{
fprintf(stderr,"Could not open one or more files ");
exit(EXIT_FAILURE);
}

close(0);
dup(inFd);
close(1);
dup(outFd);
close(2);
dup(errFd);
  
/* Run CALC_PROGNAME, if fails generate output: */
execl(CALC_PROGNAME,CALC_PROGNAME,fileName,NULL);
fprintf(stderr,"Could not execl %s ",CALC_PROGNAME);
exit(EXIT_FAILURE);  

}
/* Parent reads files: */
else
{
  
/* Wait and check status of child process, if it crashes return STD_ERROR_MSG: */
int status;
pid_t return_pid = waitpid(calcPid, &status, WNOHANG);
  
if (return_pid == -1)
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
  
/* If child process EXIT_SUCCESS, then run parent process: */
if (return_pid == calcPid)
{
char   fileName[BUFFER_LEN];
  
snprintf(fileName,BUFFER_LEN,"%d%s",fileNum,FILENAME_EXTENSION);
int numBytes = 0;
  
  
int   outFd   = open(OUTPUT_FILENAME,O_RDONLY|O_CREAT,0660);
int   errFd   = open(ERROR_FILENAME, O_RDONLY|O_CREAT,0660);

if ( (outFd < 0) || (errFd < 0) )
{
fprintf(stderr,"Could not open one or more files ");
exit(EXIT_FAILURE);
}
  
while ( (numBytes = read(outFd, fileName, BUFFER_LEN)) > 0)
read(errFd, &fileName[numBytes], BUFFER_LEN);
  
close(0);
dup(outFd);
close(1);
dup(errFd);
}
}
}
  
else if (command == DELETE_CMD_CHAR)
{
if (fileNum > 0)
{
fileNum = unlink(buffer);
write(fd, STD_OKAY_MSG, sizeof(STD_OKAY_MSG));
}
else
write(fd, STD_ERROR_MSG, sizeof(STD_ERROR_MSG));
}
  
else if (command == QUIT_CMD_CHAR)
{
/* Send STD_BYE_MSG back to the client and set shouldContinue to 0 to quit the loop: */   
write(fd, STD_BYE_MSG, sizeof(STD_BYE_MSG));
shouldContinue = 0;
}
}
  
}
  
  
printf("Thread %d quitting. ",threadNum);
return(NULL);
}


// PURPOSE: To decide a port number, either from the command line arguments
//   'argc' and 'argv[]', or by asking the user. Returns port number.
int       getPortNum   (int   argc,
               char*   argv[]
               )
{
// I. Application validity check:

// II. Get listening socket:
int   portNum;

if (argc >= 2)
portNum   = strtol(argv[1],NULL,0);
else
{
char   buffer[BUFFER_LEN];

printf("Port number to monopolize? ");
fgets(buffer,BUFFER_LEN,stdin);
portNum   = strtol(buffer,NULL,0);
}

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


// 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
               )
{
// I. Application validity check:

// 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(THIS_PROGRAM_NAME);
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(THIS_PROGRAM_NAME);
return(ERROR_FD);
}

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

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


int       main       (int   argc,
               char*   argv[]
               )
{
// I. Application validity check:

// II. Do server:
int    port   = getPortNum(argc,argv);
int   listenFd   = getServerFileDescriptor(port);
int   status   = EXIT_FAILURE;

if (listenFd >= 0)
{
doServer(listenFd);
close(listenFd);
status   = EXIT_SUCCESS;
}

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

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