我正在尝试将STDOUT和STDERR重定向到套接字。
我做了:
if(fork() == 0)
{
dup2(newsock, STDOUT_FILENO);
dup2(newsock, STDERR_FILENO);
execvp();
}
不知何故,它只显示了输出的第一个小部分。
例如,当我尝试执行ls或mkdir时,它显示在“mkdir”上。
有什么问题?
我尝试过它可行,但我只能重定向一个STDOUT或STDERR
close(1);
dup(newsock);
非常感谢。
答案 0 :(得分:9)
您对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一起使用但不与您的客户端程序一起使用,那么在客户端程序中查找问题。
答案 1 :(得分:3)
您对dup2
的使用是正确的。您的写入调用不会写入您提供的整个缓冲区,因为远程对等方尚未接收到数据,并且为此分配的内核缓冲区可能已满。典型的缓冲区大小为64KB。您应该确保接收器正在接收数据,并将您的写入包装在一个循环中。或者,使用MSG_SENDALL
和send
系统调用。
答案 2 :(得分:1)
再次阅读man dup2
页面(摘录):
SYNOPSIS
int dup2(int oldfd, int newfd);
DESCRIPTION
dup2() makes newfd be the copy of oldfd, closing newfd
所以它应该是dup2 (STDOUT_FILENO, newsock);
答案 3 :(得分:0)
我认为问题在于stderr和stdout在某些系统上是相同的