开发者

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);
    }
  }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜