tags:

views:

167

answers:

2

Hi, this is my function:

    void connection(int sock)   // sock is a descriptor of socket
{
        char buffer[MAX];
        int n;                 // number of bytes read or write into a socket
        int f;
        f = fork();
if(write(sock,"HELLO\n", 5) < 0)
{
perror("Error: \n");
}
write(sock, "\n> ",3);
do {

memset(buffer,'0',MAX); // 

n = read(sock,buffer,MAX -1 );

if (strncmp("get",buffer,3) == 0)
        {

        if(f == 0)
        {
        write(sock, "TOP:\n",4);
        dup2(sock,1);
        if(execl("/usr/bin/top","/usr/bin/top","-bn1",0) == -1)
        write(sock, "ERROR",5);

        }
        else

        {
        waitpid(f, NULL, 0);
        write(sock, "\n> ",3);
        }

        }
else if (strncmp("quit",buffer,4) == 0)
{
        write(sock, "EXIT\n",4);
        close(sock);
        exit(0);
}

else
{
write(sock,"Wrong order\n", 12);
write(sock, "> ",2);
}

}
while(n);
}

This function is responsible for information exchange among client and server. The server should sends the results of "top" action.

This function is a part of TCP server program.

When client connect with server with telnet help, he see:

> Hello
> //(and here I can write "get", to see top results)

I' d like to see ">" again, after call "get", so I' ve put: else

        {
        waitpid(f, NULL, 0);
        write(sock, "\n> ",3);
        }

But I do not see my ">". I can see it, only when I write in telnet something else. What should I put in my child process in fork, to invoke my parent process?

Regards.

+3  A: 

Both parent and child send HELLO to the socket. And both read from the socket. That's a strange behavior.

If what you want is to open a separate process to manage the connection, you should fork at the beginning as you now do, and immediately separate the parent and child processes with the 'if (f==0)'. After that the child should send the HELLO, etc., if I correctly understood your intention.

pau.estalella
So, do you suggest to move this lines, which are in else{} into if(f==0) {} ?
Mateusz
Mike D. gives a far more detailed answer.
pau.estalella
+4  A: 

1) memset(buffer,'0',MAX); writes the ASCII character '0' to all bytes in your buffer. Therefore, there is no guarantee that the string you read in null-terminated.

2) Your "command line" handling doesn't handle a closed socket right. It exits the do...while loop, returning from connection() ... which is probably not what you want. You probably want it to do the same thing as a "quit" command. The "quit" command cose should break; instead of exit(0);, and the exit(0); should be put after the while(n);.

3) The child process and parent process will, right after fork(), have the same files open. Each process should close the files it will no longer use. At the very least, this means the parent (f != 0) needs to close sock because it is now the property of the child. Also, the server (actually, listener) process should go back to listening for more connections after spawning the child process. To do this, put this after the f = fork() line:

if(f != 0)  // Or just 'if(f)' if your coding standards allow it.
{   // Parent continues here
    close(sock);
    return; // Or 'return f;' if you want to save the child's process ID for later.
}
// Child starts here

If the parent process has files open that the child should not mess with, they should be closed right after this if(f != 0) block.

4) There's no guarantee that a call to read() will get you a single line, unless something is performing line buffering (maybe your terminal?).

5) You should write your prompt out right before you do the read(), inside your do...while loop.

6) When you execl(), your current process goes away, and there's no way to get back. I recommend you investigate the popen() set of commands and use them instead.

Mike D.