Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sun-barr!olivea!uunet!mcsun!hp4nl!aie!hansb From: hansb@aie.uucp (Hans Bayle) Newsgroups: comp.unix.sysv386 Subject: non-blocking accept(3I) wanted. (ISC's tcp/ip) Message-ID: <1991Apr25.135618.23478@aie.uucp> Date: 25 Apr 91 13:56:18 GMT Organization: A.I. Engineering BV, Amsterdam, Netherlands Lines: 182 I have a little problem with the tcp/ip package that comes with Interactive Unix System V 386/ix. The manual says that when calling accept(3I) is done with the file descriptor (in this case a socket) set to non-blocking, that accept() will return immediately even when there are no pending connections present on the queue. In that case it should return EAGAIN. I isolated the problem in the two following tiny programs: A server: #include #include #include #include #include #include #include #include main() { int on=1; int s, r, ns, length; char buf[BUFSIZ]; char hostname[128]; struct sockaddr_in server; struct sockaddr_in client; FILE *fin; struct hostent *hp, *gethostbyname(); if (gethostname(hostname, sizeof hostname) == -1) { perror("gethostname failed"); exit(1); } /* get host by name from nameserver */ if((hp= gethostbyname(hostname)) < 0) { perror("client: gethostbyname failed"); exit(1); } printf("\n\nServer started on %s\n\n", hp->h_name); /* initialize adress struct */ bzero((char *) &server, sizeof(server)); bcopy(hp->h_addr, &server.sin_addr, hp->h_length); server.sin_port= htons(2000); server.sin_family= hp->h_addrtype; server.sin_addr.s_addr= INADDR_ANY; /* create a new socket */ if((s=socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { perror("server socket failed"); exit(1); } if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) { perror("Server: setsockopt failed"); exit(1); } if((r=bind(s, &server, sizeof(server))) < 0) { perror("Server: bind failed"); exit(1); } if((r=listen(s, 5)) < 0) { perror("Server: listen failed"); exit(1); } fprintf(stderr, "listen\n"); for(;;) { length= sizeof(client); /* as you see, i'm using fcntl to set the socket non_blocking.... */ fcntl(s, F_SETFL, fcntl(s, F_GETFL, 0) | O_NDELAY); ns=accept(s, &client, &length); fprintf(stderr, "accept\n"); if (ns != -1) { bzero(buf, BUFSIZ); while((r= read(ns, buf, BUFSIZ)) > 0) { buf[r]= '\0'; if((r=write(ns, "ACK\n", 4)) < 0) perror("Server: write ACK failed"); else printf("Received %s", buf); bzero(buf, BUFSIZ); } } else { if (ns == EAGAIN) { printf("No clients....\n"); sleep(5); } else { perror("Server: accept failed"); exit(1); } } close(ns); fprintf(stderr, "end read\n"); } } To access the server a client: #include #include #include #include #include #include #include main(argc,argv) int argc; char **argv; { int on=1; int s, r, ns, length; char buf[BUFSIZ]; char hostname[128]; struct sockaddr_in client; struct hostent *hp, *gethostbyname(); if (argc != 2) { printf("Wrong host name.\n"); exit(1); } /* get host by name from nameserver */ if((hp= gethostbyname(argv[1])) < 0) { perror("client: gethostbyname failed"); exit(1); } printf("Client trying to connect to %s\n", hp->h_name); /* initialize adress struct client */ memset((char *)&client, '\0', sizeof(client)); memcpy((char *)&client.sin_addr, hp->h_addr, hp->h_length); client.sin_port= htons(2000); client.sin_family= hp->h_addrtype; /* create a new socket */ if((s=socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { perror("client socket failed"); exit(1); } if((r=connect(s, &client, sizeof(client))) < 0) { perror("client connect failed"); exit(1); } bzero(buf, BUFSIZ); r= read(0, buf, BUFSIZ); if((r=write(s, buf, r)) < 0) { perror("client write failed"); exit(1); } bzero(buf, BUFSIZ); if((r=read(s, buf, BUFSIZ)) >= 0) { if(strncmp(buf, "ACK", 3)!= 0) { buf[r-1]= '\0'; printf("Received %s, instead of ACK\n", buf); } } else printf("No response\n"); } The problem is that accept() in the server just blocks, even with the fcntl() call.. Is this a bug in the lib, the manual or in my program?