Question
I'm not sure what I'm doing wrong? .. I cannot get the port to connect to the socket at all. When I enter a port
I'm not sure what I'm doing wrong? .. I cannot get the port to connect to the socket at all. When I enter a port number the client does nothing.
Instructions:
Write a server that is able to:
- Receive input from a socket
- Give that input to a child process on its command line
- Get the child process's response from a pipe
- Send the response back to the client via the socket
The input will be a simple language of string duplication and concatenation:
-
Implementing doServer(int listenFd) (20 Points):
doServer() should have a loop in which it waits for a client to connect to listenFd. When a client does, it should:
- malloc() or calloc() 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.
-
void* handleClient(void* vPtr) (30 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:
// II.B. Read command: char buffer[BUFFER_LEN]; char command; char* textPtr; int shouldContinue = 1; while (shouldContinue) { read(fd,buffer,BUFFER_LEN); printf("Thread %d received: %s ",threadNum,buffer); command = buffer[0]; textPtr = buffer + 2; // YOUR CODE HERE }
It read()s a line of text from the client into buffer[], and parses the line into a command character, and the rest of the text textPtr.
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:
printf("Thread %d quitting. ",threadNum); return(NULL);
- The thread id and the file descriptor are passed, but they come in as a void* pointer.
-
command == STRING_LANG_CMD_CHAR (40 Points):
This one applies the string language to textPtr by:
- Opens a pipe for the child process to communicate back to the parent. If opening the pipe fails then it sends STD_ERROR_MSG back to the client.
- fork()s a child process. This child process:
- Sends its stdout to the output end of this pipe
- Executes the program STRING_LANG_PROGNAME with the text in cPtr as its command line argument.
- If the child process cannot execute the program, then it sends STD_ERROR_MSG back to the parent process using fd and does exit(EXIT_FAILURE).
- Meanwhile, the parent process does a read() from the input end of the pipe. It puts an ending '\0' at the end of the text it read, does a wait() to get the zombie child, and sends the text 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
CODE:
/*-------------------------------------------------------------------------* *--- ---* *--- stringLangServer.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 1a ---* *--- ---* *-------------------------------------------------------------------------*/ // Compile with: // $ gcc stringLangServer.c -o stringLangServer -lpthread //--- Header file inclusion ---// #include "clientServer.h" #include// For pthread_create() //--- 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 "stringLangServer" const int ERROR_FD = -1; //--- Definition of global vars: ---// // PURPOSE: To be non-zero for as long as this program should run, or '0' // otherwise. //--- Definition of functions: ---// // PURPOSE: To: // (1) create a pipe // (2) fork() a child process. This child process will: // (2a) close() its file descriptor to stdout, // (2b) send its output from the pipe to the close stdout file descriptor // (2c) Run the program STRING_LANG_PROGNAME with cPtr on the cmd line // (2d) Send an error message back to the client on file descriptor 'fd' // if the execl() failed. // (3) get input from the pipe, put the '\0' char at the end // (4) wait() for the child process to end // (5) send the input back to the client using file descriptor 'fd' void stringLangFile (int socketFd, const char* cPtr ) { // I. Application validity check: // II. Apply string language file: // YOUR CODE HERE // III. Finished: } // PURPOSE: To cast 'vPtr' to the pointer type coming from 'doServer()' // that points to two integers. Then, to use those two integers, // one as a file descriptor, the other as a thread number, to fulfill // requests coming from the client over the file descriptor socket. // Returns 'NULL'. void* handleClient (void* vPtr ) { // I. Application validity check: // II. Handle client: // YOUR CODE HERE int fd = 0; // <-- CHANGE THAT 0! int threadNum = 0; // <-- CHANGE THAT 0! // YOUR CODE HERE // III. Finished: printf("Thread %d quitting. ",threadNum); return(NULL); } // PURPOSE: To run the server by 'accept()'-ing client requests from // 'listenFd' and doing them. void doServer (int listenFd ) { // I. Application validity check: // II. Server clients: pthread_t threadId; pthread_attr_t threadAttr; int threadCount = 0; while (1) { // YOUR CODE HERE } // YOUR CODE HERE // III. Finished: } // 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,'\0' ,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); }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started