jordan@greipa.UUCP (Jordan K. Hubbard) (06/12/85)
Thank you for all the responses on my AF_UNIX domain socket question. selecting the accepting socket works nicely. Now for another question, I've built a simplistic server/client model for testing AF_INET sockets and it doesn't work.. I've declared the server as a 'service' and done the appropriate get host and server calls and bound the socket. Connections are accepted, but the accept call returns a fd with a value of zero! This causes obvious problems when the server tries to read the new socket.. The salient portions of the client/server code follow. -- client code -- (host name is passed as 'host') struct hostent *cafe; /* host table entry */ struct servent *waiter; /* sevice file entry */ struct sockaddr_in sin;/* socket address */ if ((cafe = gethostbyname(host)) == NULL) { fprintf(stderr, "client: Unknown host %s\n", host); return(-1); } if ((waiter = getservbyname("george", "tcp")) == NULL) { fprintf(stderr, "client: george/tcp: unknown service\n"); return(-1); } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("client"); return(-1); } sin.sin_family = cafe->h_addrtype; bcopy(cafe->h_addr, (caddr_t)&sin.sin_addr, cafe->h_length); sin.sin_port = waiter->s_port; if (connect(fd, (caddr_t)&sin, sizeof(sin), 0) < 0) { perror("client"); close(fd); return(-1); } /* Send a silly message to the server */ strcpy(buff, "a burger and fries"); write(fd, buff, strlen(buff)); /* read in the response */ while (read(fd, buff, 80) > 0) printf("Waiter: '%s'\n", buff); close(fd); -- server code -- struct servent *me; /* sevice file entry */ struct sockaddr_in sin;/* socket address */ int fd; int nf, sz; /* new fd and size of sin */ char buff[132], buff2[132]; /* server buffer */ if ((sir = getservbyname("george", "tcp")) == NULL) { fprintf(stderr, "server: george/tcp: unknown service\n"); return(-1); } if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("server (socket):"); return(-1); } sin.sin_family = AF_INET; sin.sin_port = sir->s_port; sz = sizeof(sin); if (bind(fd, (caddr_t)&sin, sz) < 0) { perror("server/bind"); return(-1); } if (listen(fd, 5) < 0) { perror("server/listen"); return(-1); } /* deal with requests */ while (are_open) { if (nf = accept(fd, (caddr_t)&sin, &sz) < 0) { THIS IS THE PUD perror("server/accept"); return(-1); } while (read(nf, buff, 132)) { if (!strcmp(buff, "health inspection")) { are_open = FALSE; break; } sprintf(buff2, "%s, coming right up sir.\n", buff); write(nf, buff2, 132); } close(nf); } -- Jordan K. Hubbard @ Genstar Rental Electronics. Palo Alto, CA. {pesnta, decwrl, dual, pyramid}!greipa!jordan "Ack ack!". - William the feline
nz@wucs.UUCP (Neal Ziring) (06/27/85)
In article <240@greipa.UUCP>, jordan@greipa.UUCP (Jordan K. Hubbard) writes: > Thank you for all the responses on my AF_UNIX domain socket > question. selecting the accepting socket works nicely. > > Now for another question, I've built a simplistic server/client model > for testing AF_INET sockets and it doesn't work.. I've declared the > server as a 'service' and done the appropriate get host and server > calls and bound the socket. Connections are accepted, but the accept > call returns a fd with a value of zero! My code never works unless I bind a name to the client's socket. Actually, this is not surprising, because a name is required. Here is part of the code I use to bind a name to a socket: do { sin_sync.sin_port = htons( (--portnum)); } while( bind( sock_num, (char *)&sin_sync, sizeof(sin_sync) ) < 0 && portnum > 2); if (portnum <= 2) { PERROR("timesync: bind"); msg("timesync: couldn't name my socket! Heck!\n"); return(-4); } I think that if you bind an address to your client's socket, your code may work. Also, it sometimes helps to set options on the client's socket ONLY: if ( setsockopt( sock_num, SOL_SOCKET, SO_DEBUG, (char *) 0,0) <0) { close( sock_num ); return(-1); } Hope this is helpful. If you would like complete copies of the (working) programs from which these fragments were extracted, just drop me a letter. ...nz -- ======== ...nz (ECL - we're here to provide superior computing) Washington University Engineering Computer Laboratory old style: ... ihnp4!wucs!nz new style: nz@wucs.UUCP
mccallum@opus.UUCP (Doug McCallum) (07/01/85)
> My code never works unless I bind a name to the client's socket. > > Actually, this is not surprising, because a name is required. > > Here is part of the code I use to bind a name to a socket: > > do { > sin_sync.sin_port = htons( (--portnum)); > } while( > bind( sock_num, (char *)&sin_sync, sizeof(sin_sync) ) < 0 > && Actually, setting the port to zero works as a wildcard. The bind will then select the next free port number available. The only time something like this code sample is needed is if the portnumber desired is in the priviledged range ( <1024 ).