Advertisement

Server sending to client using fork(2) problem :(

Started by December 09, 2005 11:40 AM
7 comments, last by TheMightyDude 19 years, 2 months ago
Hello All I have started to write a multi user Server on our Linux Box which uses fork (2) to handle multiple clients. It compiles and runs fine. The only problem is I can’t get the Server to send information to the Client. Yet the Client can connect and send to the Server, the Server can then respond back to the Client fine. But I cannot get the Server to talk to the Client. I am using a modified version from "Linux Socket Programming by Example" Written by Warren W. Gay. My code is creating the Child Process right after it accepts the connection. It also applies a tx and rx file stream to the socket. Then every time some data comes in it calls the process function which processes the incoming packets. It seems to me that I need to find a way to get the parent process to talk to the child process; how this is done I don’t know. Has anyone got this working, or know how to get this to work? Any advice would be grateful If you require more info, just let me know. Thanks in advance Paul Kirby
fork(2) works by creating a new process that is a duplicate of the current running process. All of the data and variables and stuff should be the same in both process up to the time of the fork, after that they are not guaranteed to be the same.

Another way would be to open up a pipe between the two processes. I forget how its done exactly but I am sure you can find examples on google.

Heres An explanation of pipe

Edit: I took back the part about shared memory because after rereading fork I dont think it works. Pipes are probably the way to go since they were designed for inter process communication.

Have you considered using threads instead?

[Edited by - cmptrgear on December 9, 2005 12:07:13 PM]
"Pfft, Facts! Facts can be used to prove anything!" -- Homer J. Simpson
Advertisement
Thanks for replying :)

Ok, I have looked up pipe() function...

It says I have to use pipe() before fork().
How would this work for multi-connections?
To me it looks like all child processes will be using the same array var.

Sorry for my bad example :(
eg..

// create socket
...
// bind socket
...
// make it a listening socket
...
// indef for loop
...
// wait for connection
...
// accept connection
...
// pipe();
...
// fork()
...
// create rx and tx file streams
...
// set rx and tx to linebuffer mode
...
// process clients requests (while loop with fgets)
...
// close and shutdown rx and tx (SHUT_RDWR)
...
// End of for loop
...
// exit

I know that I have to use 1 for input and 1 for output, or I have to use 2 pipes if I want to have a duplex pipe.

What I want is for the parent process to be able to talk to all child processes.
So thap I could send packets like status updates, pings, chat messages updates etc.

Because as I said, with just using fork() the client can request and respond stuff yet the server can only respond and cannot request stuff.

So how exactly do I use the pipe()?
All the examples done use it with sockets :(
And the only example that I have that uses it with fork() and as I said at the top of this post, that it seems to me that its sharing the array var with all child processes :(

Or am I seeing it all wrong ?

Thanks in advance
Paul Kirby
Ok, it seems like they dont use the same info that is in the fd[] array for all child processes :)

So....
Ive set fd[] using pipe(fd); just after I accecpt the socket connection, and before I fork() the child process.
Now how do I use this to get the server to send info to the child process?

Am I right when I say, I use the fd[0] and fd[1] insted of the rx and tx FILE variables?
And where one is for reading and the other is for sending depending on which process (parent, child) is doing what would depend on the fd[0] and fd[1].

Am I right so far?

Thanks in advance
Paul Kirby
Its been a while since I have used pipes but I believe it goes like this. It may be different, like I said it has been a while since I have used pipes. I tend to stick with threads.

int fd[2];pipe(fd);FILE * writer = fopen(fd[1]);FILE * reader = 0;fork();//code to determine if I am a forked processif(I_am_a_fork)   reader = fopen(fd[0]);


You can then read and write using
fprintf() to write to the pipe
fscanf() to read from the pipe

or whatever your preferred IO routines are.
"Pfft, Facts! Facts can be used to prove anything!" -- Homer J. Simpson
Well I had a quick go at it...
Seems like it should be fdopen(fd[1],"w") or fdopen(fd[0],"r") sommit on those line.

Though I could be wrong.

I will have another try tomorrowwhen I get up.

Thanks for the help so far :)

Paul Kirby
Advertisement
You would be right, I didnt look up the function prototype of fopen before I posted. I was just lazy.
"Pfft, Facts! Facts can be used to prove anything!" -- Homer J. Simpson
Hmm, Just had ago again this morning and no joy :(

It either disconnects the client (crashes the process) or just lets them sort of connect and then does nothing.

What I will do is restart from scratch and use pipe () and fork () from the start and work from that.
I have the basic idea how my old code working, I just hope it all works fine at the end.

I don’t really want to use select(2) due to if one connection locks up I think it fubars up the other connections :( which is why I thought I would try the fork() which worked better up to a point, lets hope fork() with pipe() does the trick.

If you have any other ideas that I could try as well as what has been discussed so far.
What I basically want is a server that can handle at lease 1000 to 10000 players at once.
I know that I may need to have a cluster of said servers to achieve above the 5000 mark, but I thought depending on what is processed and what is sent in the packets would lead to how may players each cluster/server could handle at one point.

Thanks for the help.

Paul Kirby
Hello cmptrgear

I think I know where I may be going wrong...

I may of been using it all wrong.

Ok, here on how I think it should go together.

I still use my code as it was...
I add the pipe () as you said...
I only use the piped connection to get the Parent to talk to the Child.
And if need be I can add another pipe () if I need to send both ways (duplex).

Ok, problem now is...
How do I know when there is stuff that the Child needs to read from the Parent?
I know I can use fprintf () and fscanf () to read and write through the pipe, but when do I do this?

Would I have to check this in the while loop:
[Orig]
/*
* Process client's requests:
*/
while (fgets(buf,sizeof(buf),rx))
{
rpn_process(tx,buf);
}

If it is need to be in that while loop where about would I put it?
[Test]
/*
* Process client's requests:
*/
while (fgets(buf,sizeof(buf),rx) || fgets(buf2,sizeof(buf2),reader))
{
p_len = strlen(buf2);
printf("DEBUG: Parent Packet Size: %d bytes\n",p_len);
if(p_len)>0)
{
printf ("Oooh the Parent wants me\nParent Sent: %s\n",buf2);
}
rpn_process(tx,buf);
}

Like that?
or
[Test2]
/*
* Process client's requests:
*/
while (fgets(buf,sizeof(buf),rx))
{
if(fgets(buf2,sizeof(buf2),reader))
{
p_len = strlen(buf2);
printf ("DEBUG: Parent Packet Size: %d bytes\n",p_len);
printf ("Oooh the Parent wants me\nParent Sent: %s\n",buf2);
}
rpn_process(tx,buf);
}

Because to me this version will only process while it has the client connected, which may be ok.

Any update on this?

This topic is closed to new replies.

Advertisement