[net.unix] AF_INET sockets, code examples needed.

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 ).