hansb@aie.uucp (Hans Bayle) (04/25/91)
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 <stdio.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> 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 <stdio.h> #include <errno.h> #include <sys/types.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> 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?
david@bacchus.esa.oz.au (David Burren) (04/29/91)
In <1991Apr25.135618.23478@aie.uucp> hansb@aie.uucp (Hans Bayle) writes: >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: I don't have ISC manuals on hand, but on my Sony NEWS (running a BSD) the error is EWOULDBLOCK. >Is this a bug in the lib, the manual or in my program? Your program looks ok, and I suspect the library should be returning EWOULDBLOCK in order to be compatible with other OSes, so my guess is the manual. _____________________________________________________________________________ David Burren [Athos] Email: david@bacchus.esa.oz.au Software Development Engineer Phone: +61 3 819 4554 Expert Solutions Australia, Hawthorn, VIC Fax: +61 3 819 5580