How can I get my client to wait to open a file until my server has made it?
I have a client/server program. My Client process spawns my server process using a `fork()` and `system()` call. The client and the server are meant to communicate to each other through named piped, that is a requirement of my homework. The client and the server are supposed to initially send a message to the other one, through a pipe, to confirm that a connection is made. My issue is that my client is trying to open one of the named pipes before the server has a chance to make it. This doesn't always happen though. Occasionally, it will run fine. Is there some way to synchronize this?
My overall goal is to get a filename and search target from the user, send those to the server through a named pipe. And the server searches for the target and sends info back.
OUTPUT:
Code:
Client: PID 2986 - Running on Tue Sep 30 20:59:28 2014
Client: PID 2986 - Enter File Name: largeSampleText.txt
Server PID 2988 - Running on Tue Sep 30 20:59:32 2014
Server: PID 2988 - Synchronized to Client.//This means the client-to-server fifo is working
There was an error opening serverToClientfifo//This means client couldn't open the server-to-client fifo
error is: 2//This means the fifo doesn't exist yet
Client: PID 2986 - Enter Target:
s
Client: PID 2986 - Input File >>>largeSampleText.txt<<<
Client: PID 2986 - Target >>>s<<<
Client received unexpected connection message
Message was: D(Ã*ì4
Terminating
CORRECT OUTPUT:
Code:
Client: PID 2542 - Running on Tue Sep 30 20:58:44 2014
Client: PID 2542 - Enter File Name: largeSampleText.txt
Server PID 2557 - Running on Tue Sep 30 20:58:54 2014
Server: PID 2557 - Synchronized to Client.
Client: PID 2542 - Enter Target:
was
Client: PID 2542 - Input File >>>largeSampleText.txt<<<
Client: PID 2542 - Target >>>was<<<
Client: PID 2542 - Synchronized to Server
//The results of the search follows
RELEVANT CLIENT CODE:
Code:
int main()
{
char requestedFileName[1024];
//Get initial information on the client
pid_t clientPID = getpid();
time_t currentTime = time(0);
char* stringTime= ctime(¤tTime);
cout << "Client: PID " << clientPID <<" - Running on "
<< stringTime;
//Get file name from user
cout << "Client: PID " << clientPID <<" - Enter File Name: ";
cin >> requestedFileName;
//Launch the server process
int status = 0;
pid_t childPID;
if(fork() == 0)
{
childPID = getpid();
status = system("pipedServer");
return 0;
}
//Create the client -> server pipe and send connection message
mkfifo ("clientToServerfifo", 0666);
mkfifo("serverToClientfifo",0666);
int fd = open("clientToServerfifo", O_WRONLY);
char connectionMessage[] = "client attempting to connect";
write(fd, connectionMessage, sizeof(connectionMessage));
//Connect to fifo as reader
int fd2, maxBufferSize = 1024;
char buffer[maxBufferSize];
char expectedConnectionMessage[]="server attempting to connect";
fd2 = open("serverToClientfifo", O_RDONLY);
if(fd2 == -1) {cout <<"There was an error opening serverToClientfifo" <<endl;
cout << "error is: " <<errno <<endl;}
// Recieve connection message
read(fd2, buffer, maxBufferSize);
//Get target search term
char requestedTarget[1024];
cout << "Client: PID " << clientPID <<" - Enter Target: " <<endl;
cin >> requestedTarget;
cout << "Client: PID " << clientPID <<" - Input File " << ">>>"
<<requestedFileName<<"<<<"<<endl;
cout <<"Client: PID " << clientPID <<" - Target " << ">>>"
<< requestedTarget << "<<<" << endl;
if(strcmp(buffer,expectedConnectionMessage) == 0)
{
cout <<"Client: PID " << clientPID <<" - Synchronized to Server" << endl;
}
else
{
cout <<"Client received unexpected connection message" << endl;
cout << "Message was: " << buffer << endl;
cout << "Terminating" << endl;
kill(childPID, 0);
return 0;
}
//Send file name and search term to server
write(fd, requestedFileName, sizeof(requestedFileName));
write(fd, requestedTarget, sizeof(requestedTarget));
//Other code follows
RELEVANT SERVER CODE:
Code:
int main()
{
//Get basic server information
pid_t serverPID = getpid();
time_t currentTime = time(0);
char* stringTime = ctime(¤tTime);
cout << "Server PID " << serverPID << " - Running on "
<< stringTime;
//Connect to fifo as reader
int fd, maxBufferSize = 1024;
char buffer[maxBufferSize];
char expectedConnectionMessage[]="client attempting to connect";
fd = open("clientToServerfifo", O_RDONLY);
if(fd == -1) cout <<"There was an error opening clientToServerfifo" <<endl;
//Recieve connection message
read(fd, buffer,maxBufferSize);
if(strcmp(buffer,expectedConnectionMessage) == 0)
{
cout <<"Server: PID " << serverPID << " - Synchronized to Client." <<endl;
}
else
{
cout << "Server received unexpected connection message " << endl;
cout<<"Message: " << buffer <<endl;
cout << "Terminating" <<endl;
return 0;
}
//Create server -> client fifo and send connection message
mkfifo ("serverToClientfifo", 0666);
int fd2 = open("serverToClientfifo", O_WRONLY);
char connectionMessage[] = "server attempting to connect";
write(fd2, connectionMessage, sizeof(connectionMessage));
//other code follows
EDIT: I tried creating both of my fifos in my client and my output changed to this
Code:
Client: PID 3150 - Running on Tue Sep 30 21:23:17 2014
Client: PID 3150 - Enter File Name: largeSampleText.txt
Client: PID 3150 - Enter Target:
Server PID 3153 - Running on Tue Sep 30 21:23:21 2014
was
Client: PID 3150 - Input File >>>largeSampleText.txt<<<
Client: PID 3150 - Target >>>was<<<
Client: PID 3150 - Synchronized to Server
Server received unexpected connection message
Message: was
Terminating
So It appears like the client went ahead and put `requestedFileName` and`requestedTarget`into the pipe and the server read out `requestedTarget` instead of the connection message. Not sure why thoughand the server read out `requestedTarget` instead of the connection message. Not sure why though
Re: How can I get my client to wait to open a file until my server has made it?
I'm not a unix/linux programmer so there may be a better way of doing it on your system - but an 'easy' way would be that if the open failed to then sleep for say a second and then retry the open. Only if the open retries exceeds a limit (eg 3) is an error reported.