bash 将 STDOUT 和 STDERR 重定向到 C 中的套接字?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8100817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirect STDOUT and STDERR to socket in C?
提问by JJ Liu
I am trying to redirect STDOUT AND STDERR to a socket.
我正在尝试将 STDOUT 和 STDERR 重定向到套接字。
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.
例如,当我尝试执行 ls 或 mkdir 时,它显示在“mkdir”上。
What's the problem?
有什么问题?
I tried the flollowing it works, but I can only redirect one of STDOUT or STDERR
我尝试了以下它的工作原理,但我只能重定向 STDOUT 或 STDERR 之一
close(1);
dup(newsock);
Thanks a lot.
非常感谢。
回答by Dmitri
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:
您的使用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 */
}
}
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.
以上是一个非常基本的服务器(一次只有一个客户端)的核心,当它接收到一个连接时,它会派生一个新进程来运行一个命令,并通过套接字将其 stderr 和 stdout 发送到客户端。希望您可以通过检查来解决您的问题——但不要只是复制代码而不了解它的作用。
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.
首先尝试通过与 telnet 客户端连接来进行测试……如果它可以与 telnet 一起使用但不能与您的客户端程序一起使用,那么在您的客户端程序中查找问题。
回答by Matt Joiner
Your usage of dup2is 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 sendsyscall.
你的用法dup2是正确的。您的写入调用并未写入您提供给它们的整个缓冲区,因为远程对等方尚未收到数据,为此分配的内核缓冲区可能已满。典型的缓冲区大小为 64KB。您应该确保接收器正在接收数据,并将您的写入包裹在一个循环中。或者使用MSG_SENDALL, 和send系统调用。
回答by Basile Starynkevitch
Read again the man dup2page (excerpts):
再次阅读man dup2页面(摘录):
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);
所以应该是 dup2 (STDOUT_FILENO, newsock);

