我有这个大多数原型的TCP套接字服务器接受连接,然后运行用户指定的程序与另一方交谈。神秘的事情是调用write()并返回,但没有输出传递给客户端。
strace输出(作为执行程序运行“cat”)如下所示:
[pid 8142] read(0, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 32768) = 292
[pid 8142] write(1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 292) = 292
[pid 8142] read(0, "", 32768) = 0
[pid 8142] close(0) = 0
[pid 8142] close(1) = 0
[pid 8142] close(2) = 0
在客户端,没有任何事情发生:
shell$ seq 100 | nc localhost 4445
shell$
我已经准备好相信execve'd程序应该更像套接字来处理套接字,就像使用send / recv / shutdown而不是read / write / close一样 - 但是我已经看过的文档了现在似乎建议close()应该按设计工作,只有关闭连接才需要关闭。 The Unix Sockets FAQ提到未发送未发送数据而不设置任何SO_LINGER选项,并且Linux手册页套接字(7)声称“当套接字作为exit(2)的一部分关闭时,它总是不散 在后台。“给它足够的输出会导致第一部分输出到客户端。
为了完整起见,这是程序......
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <linux/net.h>
#include <netinet/in.h>
static int sock_fd_listen;
static struct sockaddr_in my_addr = {PF_INET, 0x5d11, 0x0100007f};
static struct
static int one=1;
static int sockargs[]={0, 0, 0};
extern char **environ;
void step1()
{
int retval;
sock_fd_listen=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
retval=bind(sock_fd_listen, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr_in));
if (retval==-1) {
perror("bind");
exit(1);
}
setsockopt(sock_fd_listen, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
listen(sock_fd_listen, 5);
}
void main(int argc, char *argv[])
{
static char buf[4096];
int nconn=0;
step1();
while (1) {
int conn_sock;
pid_t pid;
sockargs[0]=sock_fd_listen;
conn_sock=accept(sock_fd_listen,NULL,NULL);
pid=fork();
if (pid==0) {
dup2(conn_sock,0);
dup2(conn_sock,1);
close(conn_sock);
execve(argv[1],argv+1,environ);
fprintf(stderr, "execve failed: %s\n",strerror(errno));
exit(-1);
} else {
close(conn_sock);
}
}
}