Перенаправить STDOUT и STDERR в сокет в C? - PullRequest
4 голосов
/ 12 ноября 2011

Я пытаюсь перенаправить STDOUT и STDERR в сокет.

Я сделал:

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

Каким-то образом он показал только первую маленькую часть вывода.

например, он показывал на «mkdir», когда я пытался выполнить ls или mkdir.

В чем проблема?

Я попытался выполнить следующее, но я могу перенаправить только один изSTDOUT или STDERR

close(1);
dup(newsock);

Большое спасибо.

Ответы [ 3 ]

9 голосов
/ 12 ноября 2011

Ваше использование dup2() выглядит нормально, поэтому проблема, вероятно, в другом месте. Простая программа, которую я собрал для тестирования, не имеет проблем, с которыми вы сталкиваетесь, поэтому я просто рассмотрю ее суть (вокруг области fork() / execvp()), а некоторая проверка ошибок для краткости опущена:

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 */
  }
}

Выше приведено ядро ​​базового сервера (только одного клиента за раз), который, когда получает соединение, создает новый процесс для запуска команды и отправляет свои stderr и stdout клиенту через сокет. Надеемся, что вы сможете решить свою проблему, изучив ее, но не просто копируйте код, не понимая, что он делает.

Попробуйте выполнить тестирование, сначала подключившись к клиенту telnet ... если он работает с telnet, но не с вашей клиентской программой, то найдите проблемы в вашей клиентской программе.

3 голосов
/ 12 ноября 2011

Ваше использование dup2 правильно. Ваши вызовы записи не записывают весь буфер, который вы им предоставляете, поскольку данные еще не были получены удаленным узлом, и буфер ядра, выделенный для этого, вероятно, заполнен. Типичный размер буфера составляет 64 КБ. Вы должны убедиться, что получатель получает данные, и обернуть ваши записи в цикл. В качестве альтернативы используйте MSG_SENDALL и системный вызов send.

1 голос
/ 12 ноября 2011

Прочитайте еще раз страницу man dup2 (выдержки):

 SYNOPSIS
   int dup2(int oldfd, int newfd);

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

Так должно быть dup2 (STDOUT_FILENO, newsock);

...