data disappearing in a (TCP) socket
I have got this mostly-prototypical TCP socket server that accepts a connection and then runs a user-specified program to talk to the other side. The mysterious thing is that write() is called, and returns, but no output comes through to the client.
The strace output (running "cat" as the executed program) looks like this:
[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
while on the client side nothing at all happens:
shell$ seq 100 | nc localhost 4445
shell$
I'd be ready to believe that the execve'd program should treat the socket more socket-like, as in using send/recv/shutdown instead of read/write/close - but the documentation I've seen up to now seems to suggest that close() should work as designed and shutdown would only be necessary for half-closing a connection. The Unix Sockets FAQ mentions that unsent data should be flushed on close without setting any SO_LINGER options, and the Linux man page socket(7) claims that "When the socket is closed as part of exit(2), it always lingers in the background." Giving it enough output causes the first part to make it to the client.
For the sake of completeness, here is the program...
#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_so开发者_JAVA百科ck,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);
}
}
}
精彩评论