Redirect STDOUT and STDERR to socket in C?

2019-02-14 14:58发布

I am trying to redirect STDOUT AND STDERR to a socket.

I did:

if(fork() == 0)
{
   dup2(newsock, STDOUT_FILENO);
   dup2(newsock, STDERR_FILENO);
   execvp();
}

Somehow, it only showed the first little part of the output.

for example, it showed on "mkdir" when I try to execute ls or mkdir.

What's the problem?

I tried the flollowing it works, but I can only redirect one of STDOUT or STDERR

close(1);
dup(newsock);

Thanks a lot.

3条回答
Rolldiameter
2楼-- · 2019-02-14 15:30

Read again the man dup2 page (excerpts):

 SYNOPSIS
   int dup2(int oldfd, int newfd);

 DESCRIPTION
   dup2() makes newfd be the copy of oldfd, closing newfd 

So it should be dup2 (STDOUT_FILENO, newsock);

查看更多
欢心
3楼-- · 2019-02-14 15:43

Your use of dup2() looks fine, so the problem is probably elsewhere. The simple program I threw together to test with does not have the issues you are experiencing, so I'll just go over the core of it (around the fork()/execvp() area) with some error checking omitted for brevity:

int    lsock, /* listening socket */
       csock; /* active connection's socket */
pid_t  cpid;  /* child process ID from fork() */
char   *cmd = "somecommand";
char   *cmd_args[] = { "somecommand",
                       "firstarg",
                       "secondarg",
                       "howevermanyargs",
                       NULL }; /* note: last item is NULL */
/*  ... 
    call socket(), bind(), listen(), etc.
    ... */

for (;;) {  /* loop, accepting connections */
  if ( (csock = accept( lsock, NULL, NULL )) == -1) exit(1);
  cpid = fork();
  if (cpid < 0) exit(1);  /* exit if fork() fails */
  if ( cpid ) {
    /* In the parent process: */
    close( csock ); /* csock is not needed in the parent after the fork */
    waitpid( cpid, NULL, 0 ); /* wait for and reap child process */
  } else {
    /* In the child process: */
    dup2( csock, STDOUT_FILENO );  /* duplicate socket on stdout */
    dup2( csock, STDERR_FILENO );  /* duplicate socket on stderr too */
    close( csock );  /* can close the original after it's duplicated */
    execvp( cmd, cmd_args );   /* execvp() the command */
  }
}

The above is the core of a very basic server (only one client at a time) that, when it receives a connection, forks a new process to run a command and sends its stderr and stdout to the client over the socket. Hopefully you can solve your problem by examining it -- but don't just copy the code without understanding what it does.

Try testing by connecting with a telnet client first... if it works with telnet but not with your client program, then look for problems in your client program.

查看更多
戒情不戒烟
4楼-- · 2019-02-14 15:52

Your usage of dup2 is correct. Your write calls are not writing the entire buffer you're giving them, as the data hasn't been received by the remote peer yet, and the kernel buffer allocated for this is likely full. The typical buffer size is 64KB. You should make sure that the receiver is receiving the data, and wrap your writes in a loop. Alternatively use MSG_SENDALL, and the send syscall.

查看更多
登录 后发表回答