Re: select + stderr
From: Thomas Beneke (thomas.beneke_at_web.de)
Date: 01/21/05
- Next message: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Previous message: Azzedine: "Need help with socket communication"
- In reply to: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Next in thread: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Reply: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Fri, 21 Jan 2005 16:20:43 +0100
Jens.Toerring@physik.fu-berlin.de wrote:
> Thomas Beneke <thomas.beneke@web.de> wrote:
>
>>I have a client - server, but this works only for stdout.
>
>
> What works? What means stdout in the context of a server-client pair?
>
>
>> What do I have
>>to change . If I send a 'ls' to the server, I get the correct response
>>on the client side. If I send a 'ls /sdfdsfdlfsdl' ( a non existing
>>file), I get the error message on server side on stderr, but on client
>>side on stdout.
>
>
>>while (FD_ISSET(sockfd, &rfdset))
>
>
> I don't understand what this is good for - using the FD_ISSET macro
> only really makes sense *after* you called select().
>
>
>>{
>> if (select( fd+1 , &rfdset, NULL, NULL, NULL) < 0) {
>> if (errno != EINTR) {
>> fprintf(stderr,"select failed\n");
>> exit(1);
>> }
>> }
>> if (FD_ISSET(sockfd, &rfdset)) {
>> if ( (numbytes = recv(sockfd, buffer, sizeof(buf), MSG_WAITALL))
>>< 0 )
>
>
> Are you sure the MSG_WAITALL is appropriate here? What is supposd to
> happen when the message sent by the server is less than sizeof(buf)
> bytes?
>
>
>> {
>> fprintf(stderr,"recv failed.\n");
>> exit(1);
>> }
>> if ( numbytes ) {
>> if ( (write(STDOUT_FILENO, buffer, numbytes)) <0) {
>> fprintf(stderr,"send stdout failed\n");
>> exit(1);
>> }
>> }
>> else if (numbytes == 0 || errno != EWOULDBLOCK)
>
>
> If recv() didn't return -1 the value of errno doesn't tell you anything,
> you are never supposed to do anything with errno's value unless an error
> happened. If you feel like checking for EWOULDBLOCK (BTW, it could also
> be EAGAIN according to SUSv3) you need to do that further up where you
> check 'numbytes' for a negative value.
>
>
>> FD_CLR(sockfd, &rfdset);
>
>
> If you call select() with a cleared fdset you tell it to wait for *no*
> file descriptors to become ready for reading. I guess you do that because
> of the bogus while loop condition at the start. You better make the while
> loop an infinite loop (i.e. use "while(1)" and break from it once you find
> that you recv() returned 0 (telling you that the other side closed the
> socket).
>
>
>> }
>
>
> Before you call select() again you must set up the fdset anew - other-
> wise the case that select() did return -1 with errno being set to EINTR
> won't be dealt with correctly (or if you're dealing with more than a
> single file descriptor you call select() on).
>
>
>> }
>
>
> If I guess correctly that you want to have your client send a shell
> command to the server, have the server execute it by fork()ing and
> exec()ing a shell and send back both what the server received from
> both the stdout and stderr of the shell it spawned separately, then
> you need two logical channels between the server and the client -
> one for sending back the result from stdout and one for sending what
> appeared on stderr. For that you need either two sockets or you must
> develop some kind of protocol that allows the client to figure out
> what was what. There's nothing magical about stdout and stderr, they
> are just two different file descriptor - and when you have the server
> send what it read from both these channels intermixed via a single
> channel to the client, the client won't be able to untangle them.
>
> The simplest solution is probably to open two sockets and have the
> server write what it got from the stdout of the shell via one of the
> sockets and what it read from stderr of the shell to the other one.
> The client then listens on both these sockets, writing out what it
> receives from the first one to its stdout and what it receives from
> the second one to its stderr.
> Regards, Jens
>
> PS: I hope you're aware of the security implications of such a server
> running on your machine and have access to that server secured by a
> password (which you better don't send unencrypted over the net!).
Thank you for your reply. I've changed the select() block in my client.
Now I've added on client a second socket()
errfd = socket(AF_INET, SOCK_STREAM, 0)
a second connect()
connect(errfd, (struct sockaddr *)&server, sizeof(struct sockaddr))
and a FD_ISSET for errfd
if (FD_ISSET(errfd, &rfdset)) {
if ( (numbytes = read(errfd, buffer, sizeof(buf))) <= 0 )
.
On my server i've added a second getpeername()
getpeername(err_fd, (struct sockaddr *)&client, &client_len)
the pipe(), fork() and exec()
if (pipe(pipe_out) == -1 || pipe(pipe_err) == -1 )
exit;
switch (fork()) {
case -1:
fprintf(stderr, "fork failed.\n");
_exit(1);
case 0:
/* child */
/* stdout. */
close(pipe_out[0]);
if (dup2(pipe_out[1], 1) == -1)
fprintf(stderr, "aasapd: dup2(pipe_out).\n");
close(pipe_out[1]);
/* stderr. */
close(pipe_err[0]);
if (dup2(pipe_err[1], 2) == -1)
fprintf(stderr, "aasapd: dup2(pipe_err).\n");
close(pipe_err[1]);
execl("/bin/sh", "sh", "-c", buffer, (char *) 0);
_exit(1);
default:
default:
/* parent */
close(pipe_out[1]);
close(pipe_err[1]);
}
/* only for test */
numbytes = read(pipe_err[0], buffer, sizeof(buf));
write(err_fd, buffer, numbytes);
numbytes = read(pipe_out[0], buffer, sizeof(buf));
write(client_fd, buffer, numbytes);
The Problem now is that both outputs using stdin on my client. Why ?
Thanks,
Thomas
- Next message: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Previous message: Azzedine: "Need help with socket communication"
- In reply to: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Next in thread: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Reply: Jens.Toerring_at_physik.fu-berlin.de: "Re: select + stderr"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|