#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Makefile
#	dgramread.c
#	dgramsend.c
#	pipe.c
#	socketpair.c
#	strchkread.c
#	streamread.c
#	streamwrite.c
#	udgramread.c
#	udgramsend.c
#	ustreamread.c
#	ustreamwrite.c
#	tutor.me
#	tutor.txt
# This archive created: Mon May  3 20:19:04 1993
export PATH; PATH=/bin:/usr/bin:$PATH
cat << \SHAR_EOF > 'Makefile'
#	@(#)Makefile	6.4 (Berkeley) 6/30/90

DIR=	ps1/07.ipctut
SRCS=	tutor.me
GSRCS=	gremlins
MACROS=	-me
EXTRA=	accept.grn dgramread.c dgramsend.c gremlins pipe.c pipe.grn \
	socketpair.c socketpair.grn strchkread.c streamread.c streamwrite.c \
	udgramread.c udgramsend.c ustreamread.c ustreamwrite.c

print: paper.${PRINTER} pics.${PRINTER}
	lpr -P${PRINTER} -n paper.${PRINTER}
	lpr -P${PRINTER} -n pics.P${PRINTER

paper.${PRINTER}: ${SRCS}
	${TBL} ${SRCS} | ${ROFF} > ${.TARGET}

pics.${PRINTER}: ${GSRCS}
	${GREMLIN} ${GSRCS} | ${ROFF} > ${.TARGET}

.include <bsd.doc.mk>
SHAR_EOF
chmod 644 'Makefile'
cat << \SHAR_EOF > 'dgramread.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)dgramread.c	6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

/*
 * In the included file <netinet/in.h> a sockaddr_in is defined as follows:
 * struct sockaddr_in {
 *	short	sin_family;
 *	u_short	sin_port;
 *	struct in_addr sin_addr;
 *	char	sin_zero[8];
 * }; 
 *
 * This program creates a datagram socket, binds a name to it, then reads
 * from the socket.
 */
main()
{
	int sock, length;
	struct sockaddr_in name;
	char buf[1024];

	/* Create socket from which to read. */
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		perror("opening datagram socket");
		exit(1);
	}
	/* Create name with wildcards. */
	name.sin_family = AF_INET;
	name.sin_addr.s_addr = INADDR_ANY;
	name.sin_port = 0;
	if (bind(sock, &name, sizeof(name))) {
		perror("binding datagram socket");
		exit(1);
	}
	/* Find assigned port value and print it out. */
	length = sizeof(name);
	if (getsockname(sock, &name, &length)) {
		perror("getting socket name");
		exit(1);
	}
	printf("Socket has port #%d\en", ntohs(name.sin_port));
	/* Read from the socket */
	if (read(sock, buf, 1024) < 0)
		perror("receiving datagram packet");
	printf("-->%s\en", buf);
	close(sock);
}
SHAR_EOF
chmod 644 'dgramread.c'
cat << \SHAR_EOF > 'dgramsend.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)dgramsend.c	6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

#define DATA "The sea is calm tonight, the tide is full . . ."

/*
 * Here I send a datagram to a receiver whose name I get from the command
 * line arguments.  The form of the command line is dgramsend hostname
 * portnumber 
 */

main(argc, argv)
	int argc;
	char *argv[];
{
	int sock;
	struct sockaddr_in name;
	struct hostent *hp, *gethostbyname();

	/* Create socket on which to send. */
	sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock < 0) {
		perror("opening datagram socket");
		exit(1);
	}
	/*
	 * Construct name, with no wildcards, of the socket to send to.
	 * Getnostbyname() returns a structure including the network address
	 * of the specified host.  The port number is taken from the command
	 * line. 
	 */
	hp = gethostbyname(argv[1]);
	if (hp == 0) {
		fprintf(stderr, "%s: unknown host\n", argv[1]);
		exit(2);
	}
	bcopy(hp->h_addr, &name.sin_addr, hp->h_length);
	name.sin_family = AF_INET;
	name.sin_port = htons(atoi(argv[2]));
	/* Send message. */
	if (sendto(sock, DATA, sizeof(DATA), 0, &name, sizeof(name)) < 0)
		perror("sending datagram message");
	close(sock);
}
SHAR_EOF
chmod 644 'dgramsend.c'
cat << \SHAR_EOF > 'pipe.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)pipe.c	6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <stdio.h>

#define DATA "Bright star, would I were steadfast as thou art . . ."

/*
 * This program creates a pipe, then forks.  The child communicates to the
 * parent over the pipe. Notice that a pipe is a one-way communications
 * device.  I can write to the output socket (sockets[1], the second socket
 * of the array returned by pipe()) and read from the input socket
 * (sockets[0]), but not vice versa. 
 */

main()
{
	int sockets[2], child;

	/* Create a pipe */
	if (pipe(sockets) < 0) {
		perror("opening stream socket pair");
		exit(10);
	}

	if ((child = fork()) == -1)
		perror("fork");
	else if (child) {
		char buf[1024];

		/* This is still the parent.  It reads the child's message. */
		close(sockets[1]);
		if (read(sockets[0], buf, 1024) < 0)
			perror("reading message");
		printf("-->%s\en", buf);
		close(sockets[0]);
	} else {
		/* This is the child.  It writes a message to its parent. */
		close(sockets[0]);
		if (write(sockets[1], DATA, sizeof(DATA)) < 0)
			perror("writing message");
		close(sockets[1]);
	}
}
SHAR_EOF
chmod 644 'pipe.c'
cat << \SHAR_EOF > 'socketpair.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)socketpair.c	6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>

#define DATA1 "In Xanadu, did Kublai Khan . . ."
#define DATA2 "A stately pleasure dome decree . . ."

/*
 * This program creates a pair of connected sockets then forks and
 * communicates over them.  This is very similar to communication with pipes,
 * however, socketpairs are two-way communications objects. Therefore I can
 * send messages in both directions. 
 */

main()
{
	int sockets[2], child;
	char buf[1024];

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
		perror("opening stream socket pair");
		exit(1);
	}

	if ((child = fork()) == -1)
		perror("fork");
	else if (child) {	/* This is the parent. */
		close(sockets[0]);
		if (read(sockets[1], buf, 1024, 0) < 0)
			perror("reading stream message");
		printf("-->%s\en", buf);
		if (write(sockets[1], DATA2, sizeof(DATA2)) < 0)
			perror("writing stream message");
		close(sockets[1]);
	} else {		/* This is the child. */
		close(sockets[1]);
		if (write(sockets[0], DATA1, sizeof(DATA1)) < 0)
			perror("writing stream message");
		if (read(sockets[0], buf, 1024, 0) < 0)
			perror("reading stream message");
		printf("-->%s\en", buf);
		close(sockets[0]);
	}
}
SHAR_EOF
chmod 644 'socketpair.c'
cat << \SHAR_EOF > 'strchkread.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)strchkread.c	6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define TRUE 1

/*
 * This program uses select() to check that someone is trying to connect
 * before calling accept(). 
 */

main()
{
	int sock, length;
	struct sockaddr_in server;
	int msgsock;
	char buf[1024];
	int rval;
	fd_set ready;
	struct timeval to;

	/* Create socket */
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0) {
		perror("opening stream socket");
		exit(1);
	}
	/* Name socket using wildcards */
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = 0;
	if (bind(sock, &server, sizeof(server))) {
		perror("binding stream socket");
		exit(1);
	}
	/* Find out assigned port number and print it out */
	length = sizeof(server);
	if (getsockname(sock, &server, &length)) {
		perror("getting socket name");
		exit(1);
	}
	printf("Socket has port #%d\en", ntohs(server.sin_port));

	/* Start accepting connections */
	listen(sock, 5);
	do {
		FD_ZERO(&ready);
		FD_SET(sock, &ready);
		to.tv_sec = 5;
		if (select(sock + 1, &ready, 0, 0, &to) < 0) {
			perror("select");
			continue;
		}
		if (FD_ISSET(sock, &ready)) {
			msgsock = accept(sock, (struct sockaddr *)0, (int *)0);
			if (msgsock == -1)
				perror("accept");
			else do {
				bzero(buf, sizeof(buf));
				if ((rval = read(msgsock, buf, 1024)) < 0)
					perror("reading stream message");
				else if (rval == 0)
					printf("Ending connection\en");
				else
					printf("-->%s\en", buf);
			} while (rval > 0);
			close(msgsock);
		} else
			printf("Do something else\en");
	} while (TRUE);
}
SHAR_EOF
chmod 644 'strchkread.c'
cat << \SHAR_EOF > 'streamread.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)streamread.c	6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define TRUE 1

/*
 * This program creates a socket and then begins an infinite loop. Each time
 * through the loop it accepts a connection and prints out messages from it. 
 * When the connection breaks, or a termination message comes through, the
 * program accepts a new connection. 
 */

main()
{
	int sock, length;
	struct sockaddr_in server;
	int msgsock;
	char buf[1024];
	int rval;
	int i;

	/* Create socket */
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0) {
		perror("opening stream socket");
		exit(1);
	}
	/* Name socket using wildcards */
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = 0;
	if (bind(sock, &server, sizeof(server))) {
		perror("binding stream socket");
		exit(1);
	}
	/* Find out assigned port number and print it out */
	length = sizeof(server);
	if (getsockname(sock, &server, &length)) {
		perror("getting socket name");
		exit(1);
	}
	printf("Socket has port #%d\en", ntohs(server.sin_port));

	/* Start accepting connections */
	listen(sock, 5);
	do {
		msgsock = accept(sock, 0, 0);
		if (msgsock == -1)
			perror("accept");
		else do {
			bzero(buf, sizeof(buf));
			if ((rval = read(msgsock, buf, 1024)) < 0)
				perror("reading stream message");
			i = 0;
			if (rval == 0)
				printf("Ending connection\en");
			else
				printf("-->%s\en", buf);
		} while (rval != 0);
		close(msgsock);
	} while (TRUE);
	/*
	 * Since this program has an infinite loop, the socket "sock" is
	 * never explicitly closed.  However, all sockets will be closed
	 * automatically when a process is killed or terminates normally. 
	 */
}
SHAR_EOF
chmod 644 'streamread.c'
cat << \SHAR_EOF > 'streamwrite.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)streamwrite.c	6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

#define DATA "Half a league, half a league . . ."

/*
 * This program creates a socket and initiates a connection with the socket
 * given in the command line.  One message is sent over the connection and
 * then the socket is closed, ending the connection. The form of the command
 * line is streamwrite hostname portnumber 
 */

main(argc, argv)
	int argc;
	char *argv[];
{
	int sock;
	struct sockaddr_in server;
	struct hostent *hp, *gethostbyname();
	char buf[1024];

	/* Create socket */
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock < 0) {
		perror("opening stream socket");
		exit(1);
	}
	/* Connect socket using name specified by command line. */
	server.sin_family = AF_INET;
	hp = gethostbyname(argv[1]);
	if (hp == 0) {
		fprintf(stderr, "%s: unknown host\n", argv[1]);
		exit(2);
	}
	bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
	server.sin_port = htons(atoi(argv[2]));

	if (connect(sock, &server, sizeof(server)) < 0) {
		perror("connecting stream socket");
		exit(1);
	}
	if (write(sock, DATA, sizeof(DATA)) < 0)
		perror("writing on stream socket");
	close(sock);
}
SHAR_EOF
chmod 644 'streamwrite.c'
cat << \SHAR_EOF > 'udgramread.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)udgramread.c	6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

/*
 * In the included file <sys/un.h> a sockaddr_un is defined as follows
 * struct sockaddr_un {
 *	short	sun_family;
 *	char	sun_path[108];
 * }; 
 */

#include <stdio.h>

#define NAME "socket"

/*
 * This program creates a UNIX domain datagram socket, binds a name to it,
 * then reads from the socket. 
 */
main()
{
	int sock, length;
	struct sockaddr_un name;
	char buf[1024];

	/* Create socket from which to read. */
	sock = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (sock < 0) {
		perror("opening datagram socket");
		exit(1);
	}
	/* Create name. */
	name.sun_family = AF_UNIX;
	strcpy(name.sun_path, NAME);
	if (bind(sock, &name, sizeof(struct sockaddr_un))) {
		perror("binding name to datagram socket");
		exit(1);
	}
	printf("socket -->%s\en", NAME);
	/* Read from the socket */
	if (read(sock, buf, 1024) < 0)
		perror("receiving datagram packet");
	printf("-->%s\en", buf);
	close(sock);
	unlink(NAME);
}
SHAR_EOF
chmod 644 'udgramread.c'
cat << \SHAR_EOF > 'udgramsend.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)udgramsend.c	6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define DATA "The sea is calm tonight, the tide is full . . ."

/*
 * Here I send a datagram to a receiver whose name I get from the command
 * line arguments.  The form of the command line is udgramsend pathname 
 */

main(argc, argv)
	int argc;
	char *argv[];
{
	int sock;
	struct sockaddr_un name;

	/* Create socket on which to send. */
	sock = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (sock < 0) {
		perror("opening datagram socket");
		exit(1);
	}
	/* Construct name of socket to send to. */
	name.sun_family = AF_UNIX;
	strcpy(name.sun_path, argv[1]);
	/* Send message. */
	if (sendto(sock, DATA, sizeof(DATA), 0,
	    &name, sizeof(struct sockaddr_un)) < 0) {
		perror("sending datagram message");
	}
	close(sock);
}
SHAR_EOF
chmod 644 'udgramsend.c'
cat << \SHAR_EOF > 'ustreamread.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)ustreamread.c	6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define NAME "socket"

/*
 * This program creates a socket in the UNIX domain and binds a name to it. 
 * After printing the socket's name it begins a loop. Each time through the
 * loop it accepts a connection and prints out messages from it.  When the
 * connection breaks, or a termination message comes through, the program
 * accepts a new connection. 
 */
main()
{
	int sock, msgsock, rval;
	struct sockaddr_un server;
	char buf[1024];

	/* Create socket */
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sock < 0) {
		perror("opening stream socket");
		exit(1);
	}
	/* Name socket using file system name */
	server.sun_family = AF_UNIX;
	strcpy(server.sun_path, NAME);
	if (bind(sock, &server, sizeof(struct sockaddr_un))) {
		perror("binding stream socket");
		exit(1);
	}
	printf("Socket has name %s\en", server.sun_path);
	/* Start accepting connections */
	listen(sock, 5);
	for (;;) {
		msgsock = accept(sock, 0, 0);
		if (msgsock == -1)
			perror("accept");
		else do {
			bzero(buf, sizeof(buf));
			if ((rval = read(msgsock, buf, 1024)) < 0)
				perror("reading stream message");
			else if (rval == 0)
				printf("Ending connection\en");
			else
				printf("-->%s\en", buf);
		} while (rval > 0);
		close(msgsock);
	}
	/*
	 * The following statements are not executed, because they follow an
	 * infinite loop.  However, most ordinary programs will not run
	 * forever.  In the UNIX domain it is necessary to tell the file
	 * system that one is through using NAME.  In most programs one uses
	 * the call unlink() as below. Since the user will have to kill this
	 * program, it will be necessary to remove the name by a command from
	 * the shell. 
	 */
	close(sock);
	unlink(NAME);
}
SHAR_EOF
chmod 644 'ustreamread.c'
cat << \SHAR_EOF > 'ustreamwrite.c'
/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)ustreamwrite.c	6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define DATA "Half a league, half a league . . ."

/*
 * This program connects to the socket named in the command line and sends a
 * one line message to that socket. The form of the command line is
 * ustreamwrite pathname 
 */
main(argc, argv)
	int argc;
	char *argv[];
{
	int sock;
	struct sockaddr_un server;
	char buf[1024];

	/* Create socket */
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sock < 0) {
		perror("opening stream socket");
		exit(1);
	}
	/* Connect socket using name specified by command line. */
	server.sun_family = AF_UNIX;
	strcpy(server.sun_path, argv[1]);

	if (connect(sock, &server, sizeof(struct sockaddr_un)) < 0) {
		close(sock);
		perror("connecting stream socket");
		exit(1);
	}
	if (write(sock, DATA, sizeof(DATA)) < 0)
		perror("writing on stream socket");
}
SHAR_EOF
chmod 644 'ustreamwrite.c'
cat << \SHAR_EOF > 'tutor.me'
.\" Copyright (c) 1986 The Regents of the University of California.
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms are permitted
.\" provided that the above copyright notice and this paragraph are
.\" duplicated in all such forms and that any documentation,
.\" advertising materials, and other materials related to such
.\" distribution and use acknowledge that the software was developed
.\" by the University of California, Berkeley.  The name of the
.\" University may not be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.\"	@(#)tutor.me	6.6 (Berkeley) 3/7/89
.\"
.oh 'Introductory 4.3BSD IPC''PS1:7-%'
.eh 'PS1:7-%''Introductory 4.3BSD IPC'
.rs
.sp 2
.sz 14
.ft B
.ce 2
An Introductory 4.3BSD
Interprocess Communication Tutorial
.sz 10
.sp 2
.ce
.i "Stuart Sechrest"
.ft
.sp
.ce 4
Computer Science Research Group
Computer Science Division
Department of Electrical Engineering and Computer Science
University of California, Berkeley
.sp 2
.ce
.i ABSTRACT
.sp
.(c
.pp
Berkeley UNIX\(dg 4.3BSD offers several choices for interprocess communication.
To aid the programmer in  developing programs which are comprised of
cooperating
processes, the different choices are discussed and a series of example 
programs are presented.  These programs
demonstrate in a simple way the use of pipes, socketpairs, sockets
and the use of datagram and stream communication.  The intent of this
document is to present a few simple example programs, not to describe the
networking system in full.
.)c
.sp 2
.(f
\(dg\|UNIX is a trademark of AT&T Bell Laboratories.
.)f
.b
.sh 1 "Goals"
.r
.pp
Facilities for interprocess communication (IPC) and networking
were a major addition to UNIX in the Berkeley UNIX 4.2BSD release.
These facilities required major additions and some changes
to the system interface.
The basic idea of this interface is to make IPC similar to file I/O.
In UNIX a process has a set of I/O descriptors, from which one reads
and to which one writes.
Descriptors may refer to normal files, to devices (including terminals),
or to communication channels.
The use of a descriptor has three phases: its creation,
its use for reading and writing, and its destruction.  By using descriptors
to write files, rather than simply naming the target file in the write
call, one gains a surprising amount of flexibility.  Often, the program that
creates a descriptor will be different from the program that uses the
descriptor.  For example the shell can create a descriptor for the output 
of the `ls'
command that will cause the listing to appear in a file rather than
on a terminal.
Pipes are another form of descriptor that have been used in UNIX
for some time.
Pipes allow one-way data transmission from one process
to another; the two processes and the pipe must be set up by a common
ancestor.
.pp
The use of descriptors is not the only communication interface
provided by UNIX.
The signal mechanism sends a tiny amount of information from one 
process to another.
The signaled process receives only the signal type,
not the identity of the sender,
and the number of possible signals is small.
The signal semantics limit the flexibility of the signaling mechanism
as a means of interprocess communication.
.pp
The identification of IPC with I/O is quite longstanding in UNIX and
has proved quite successful.  At first, however, IPC was limited to
processes communicating within a single machine.  With Berkeley UNIX
4.2BSD this expanded to include IPC between machines.  This expansion
has necessitated some change in the way that descriptors are created.
Additionally, new possibilities for the meaning of read and write have
been admitted.  Originally the meanings, or semantics, of these terms
were fairly simple.  When you wrote something it was delivered.  When
you read something, you were blocked until the data arrived.
Other possibilities exist,
however.  One can write without full assurance of delivery if one can
check later to catch occasional failures.  Messages can be kept as
discrete units or merged into a stream. 
One can ask to read, but insist on not waiting if nothing is immediately
available.  These new possibilities are allowed in the Berkeley UNIX IPC
interface.  
.pp
Thus Berkeley UNIX 4.3BSD offers several choices for IPC.
This paper presents simple examples that illustrate some of
the choices.
The reader is presumed to be familiar with the C programming language
[Kernighan & Ritchie 1978],
but not necessarily with the system calls of the UNIX system or with
processes and interprocess communication.
The paper reviews the notion of a process and the types of
communication that are supported by Berkeley UNIX 4.3BSD.
A series of examples are presented that create processes that communicate
with one another.  The programs show different ways of establishing
channels of communication.
Finally, the calls that actually transfer data are reviewed.
To clearly present how communication can take place,
the example programs have been cleared of anything that
might be construed as useful work.
They can, therefore, serve as models
for the programmer trying to construct programs which are comprised of 
cooperating processes.
.b
.sh 1 "Processes"
.pp
A \fIprogram\fP is both a sequence of statements and a rough way of referring 
to the computation that occurs when the compiled statements are run.
A \fIprocess\fP can be thought of as a single line of control in a program.
Most programs execute some statements, go through a few loops, branch in
various directions and then end.  These are single process programs.
Programs can also have a point where control splits into two independent lines,
an action called \fIforking.\fP
In UNIX these lines can never join again.  A call to the system routine 
\fIfork()\fP, causes a process to split in this way.
The result of this call is that two independent processes will be
running, executing exactly the same code.
Memory values will be the same for all values set before the fork, but,
subsequently, each version will be able to change only the 
value of its own copy of each variable.
Initially, the only difference between the two will be the value returned by
\fIfork().\fP  The parent will receive a process id for the child, 
the child will receive a zero.
Calls to \fIfork(),\fP
therefore, typically precede, or are included in, an if-statement.
.pp
A process views the rest of the system through a private table of descriptors.
The descriptors can represent open files or sockets (sockets are communication
objects that will be discussed below).  Descriptors are referred to
by their index numbers in the table.  The first three descriptors are often
known by special names, \fI stdin, stdout\fP and \fIstderr\fP.
These are the standard input, output and error.
When a process forks, its descriptor table is copied to the child.
Thus, if the parent's standard input is being taken from a terminal
(devices are also treated as files in UNIX), the child's input will 
be taken from the
same terminal.  Whoever reads first will get the input.  If, before forking,
the parent changes its standard input so that it is reading from a
new file, the child will take its input from the new file.  It is
also possible to take input from a socket, rather than from a file.
.b
.sh 1 "Pipes"
.r
.pp
Most users of UNIX know that they can pipe the output of a 
program ``prog1'' to the input of another, ``prog2,'' by typing the command
\fI``prog1 | prog2.''\fP
This is called ``piping'' the output of one program
to another because the mechanism used to transfer the output is called a
pipe.
When the user types a command, the command is read by the shell, which
decides how to execute it.  If the command is simple, for example,
.i "``prog1,''"
the shell forks a process, which executes the program, prog1, and then dies.
The shell waits for this termination and then prompts for the next
command.
If the command is a compound command,
.i "``prog1 | prog2,''"
the shell creates two processes connected by a pipe. One process
runs the program, prog1, the other runs prog2.  The pipe is an I/O
mechanism with two ends, or sockets.  Data that is written into one socket
can be read from the other.  
.(z
.ft CW
.so pipe.c
.ft
.ce 1
Figure 1\ \ Use of a pipe
.)z
.pp
Since a program specifies its input and output only by the descriptor table
indices, which appear as variables or constants,
the input source and output destination can be changed without
changing the text of the program.
It is in this way that the shell is able to set up pipes.  Before executing
prog1, the process can close whatever is at \fIstdout\fP
and replace it with one
end of a pipe.  Similarly, the process that will execute prog2 can substitute
the opposite end of the pipe for 
\fIstdin.\fP
.pp
Let us now examine a program that creates a pipe for communication between
its child and itself (Figure 1).
A pipe is created by a parent process, which then forks.
When a process forks, the parent's descriptor table is copied into 
the child's.  
.pp
In Figure 1, the parent process makes a call to the system routine 
\fIpipe().\fP
This routine creates a pipe and places descriptors for the sockets
for the two ends of the pipe in the process's descriptor table.
\fIPipe()\fP
is passed an array into which it places the index numbers of the 
sockets it created.
The two ends are not equivalent.  The socket whose index is
returned in the low word of the array is opened for reading only,
while the socket in the high end is opened only for writing.
This corresponds to the fact that the standard input is the first
descriptor of a process's descriptor table and the standard output
is the second.  After creating the pipe, the parent creates the child 
with which it will share the pipe by calling \fIfork().\fP
Figure 2 illustrates the effect of a fork.
The parent process's descriptor table points to both ends of the pipe.
After the fork, both parent's and child's descriptor tables point to
the pipe.
The child can then use the pipe to send a message to the parent.
.(z
-
.bl 5.8i
-
.\" pipe.grn goes here
.sp
.ce 1
Figure 2\ \ Sharing a pipe between parent and child
.)z
.pp
Just what is a pipe?
It is a one-way communication mechanism, with one end opened
for reading and the other end for writing.
Therefore, parent and child need to agree on which way to turn
the pipe, from parent to child or the other way around.
Using the same pipe for communication both from parent to child and 
from child to parent would be possible (since both processes have 
references to both ends), but very complicated.
If the parent and child are to have a two-way conversation,
the parent creates two pipes, one for use in each direction.
(In accordance with their plans, both parent and child in the example above
close the socket that they will not use.  It is not required that unused
descriptors be closed, but it is good practice.)
A pipe is also a \fIstream\fP communication mechanism; that
is, all messages sent through the pipe are placed in order
and reliably delivered.  When the reader asks for a certain
number of bytes from this
stream, he is given as many bytes as are available, up
to the amount of the request. Note that these bytes may have come from 
the same call to \fIwrite()\fR or from several calls to \fIwrite()\fR
which were concatenated.
.b
.sh 1 "Socketpairs"
.r
.pp
Berkeley UNIX 4.3BSD provides a slight generalization of pipes.  A pipe is a
pair of connected sockets for one-way stream communication.  One may
obtain a pair of connected sockets for two-way stream communication
by calling the routine \fIsocketpair().\fP
The program in Figure 3 calls \fIsocketpair()\fP
to create such a connection.  The program uses the link for
communication in both directions.  Since socketpairs are
an extension of pipes, their use resembles that of pipes. 
Figure 4 illustrates the result of a fork following a call to 
\fIsocketpair().\fP
.pp
\fISocketpair()\fP
takes as
arguments a specification of a domain, a style of communication, and a
protocol.  
These are the parameters shown in the example.
Domains and protocols will be discussed in the next section.
Briefly,
a domain is a space of names that may be bound
to sockets and implies certain other conventions.
Currently, socketpairs have only been implemented for one
domain, called the UNIX domain.
The UNIX domain uses UNIX path names for naming sockets.  
It only allows communication
between sockets on the same machine.
.pp
Note that the header files 
.i "<sys/socket.h>"
and
.i "<sys/types.h>."
are required in this program.
The constants AF_UNIX and SOCK_STREAM are defined in 
.i "<sys/socket.h>,"
which in turn requires the file 
.i "<sys/types.h>"
for some of its definitions.
.(z
.ft CW
.so socketpair.c
.ft
.ce 1
Figure 3\ \ Use of a socketpair
.)z
.(z
-
.bl 5.8i
-
.\" socketpair.grn goes here
.sp
.ce 1
Figure 4\ \ Sharing a socketpair between parent and child
.)z
.b
.sh 1 "Domains and Protocols"
.r
.pp
Pipes and socketpairs are a simple solution for communicating between
a parent and child or between child processes.
What if we wanted to have processes that have no common ancestor
with whom to set up communication?
Neither standard UNIX pipes nor socketpairs are
the answer here, since both mechanisms require a common ancestor to
set up the communication.
We would like to have two processes separately create sockets
and then have messages sent between them.  This is often the
case when providing or using a service in the system.  This is
also the case when the communicating processes are on separate machines.
In Berkeley UNIX 4.3BSD one can create individual sockets, give them names and
send messages between them.
.pp
Sockets created by different programs use names to refer to one another;
names generally must be translated into addresses for use.
The space from which an address is drawn is referred to as a
.i domain.
There are several domains for sockets.
Two that will be used in the examples here are the UNIX domain (or AF_UNIX,
for Address Format UNIX) and the Internet domain (or AF_INET).
UNIX domain IPC is an experimental facility in 4.2BSD and 4.3BSD.
In the UNIX domain, a socket is given a path name within the file system
name space.
A file system node is created for the socket and other processes may 
then refer to the socket by giving the proper pathname.
UNIX domain names, therefore, allow communication between any two processes
that work in the same file system.
The Internet domain is the UNIX implementation of the DARPA Internet
standard protocols IP/TCP/UDP.
Addresses in the Internet domain consist of a machine network address
and an identifying number, called a port.
Internet domain names allow communication between machines.
.pp
Communication follows some particular ``style.''
Currently, communication is either through a \fIstream\fP
or by \fIdatagram.\fP
Stream communication implies several things.  Communication takes
place across a connection between two sockets.  The communication
is reliable, error-free, and, as in pipes, no message boundaries are
kept. Reading from a stream may result in reading the data sent from
one or several calls to \fIwrite()\fP
or only part of the data from a single call, if there is not enough room
for the entire message, or if not all the data from a large message
has been transferred.
The protocol implementing such a style will retransmit messages
received with errors. It will also return error messages if one tries to
send a message after the connection has been broken.
Datagram communication does not use connections.  Each message is
addressed individually.  If the address is correct, it will generally
be received, although this is not guaranteed.  Often datagrams are
used for requests that require a response from the 
recipient.  If no response
arrives in a reasonable amount of time, the request is repeated.
The individual datagrams will be kept separate when they are read, that
is, message boundaries are preserved.
.pp
The difference in performance between the two styles of communication is 
generally less important than the difference in semantics.  The
performance gain that one might find in using datagrams must be weighed
against the increased complexity of the program, which must now concern
itself with lost or out of order messages.  If lost messages may simply be 
ignored, the quantity of traffic may be a consideration. The expense
of setting up a connection is best justified by frequent use of the connection.
Since the performance of a protocol changes as it is tuned for different
situations, it is best to seek the most up-to-date information when
making choices for a program in which performance is crucial.
.pp
A protocol is a set of rules, data formats and conventions that regulate the
transfer of data between participants in the communication.
In general, there is one protocol for each socket type (stream,
datagram, etc.) within each domain.
The code that implements a protocol 
keeps track of the names that are bound to sockets,
sets up connections and	transfers data between sockets,
perhaps sending the data across a network.
This code also keeps track of the names that are bound to sockets.
It is possible for several protocols, differing only in low level
details, to implement the same style of communication within
a particular domain.  Although it is possible to select
which protocol should be used, for nearly all uses it is sufficient to
request the default protocol.  This has been done in all of the example
programs.
.pp
One specifies the domain, style and protocol of a socket when
it is created.  For example, in Figure 5a the call to \fIsocket()\fP
causes the creation of a datagram socket with the default protocol 
in the UNIX domain.
.b
.sh 1 "Datagrams in the UNIX Domain"
.r
.(z
.ft CW
.so udgramread.c
.ft
.ce 1
Figure 5a\ \ Reading UNIX domain datagrams
.)z
.pp
Let us now look at two programs that create sockets separately.
The programs in Figures 5a and 5b use datagram communication
rather than a stream.  
The structure used to name UNIX domain sockets is defined
in the file \fI<sys/un.h>.\fP
The definition has also been included in the example for clarity.
.pp
Each program creates a socket with a call to \fIsocket().\fP
These sockets are in the UNIX domain.
Once a name has been decided upon it is attached to a socket by the
system call \fIbind().\fP
The program in Figure 5a uses the name ``socket'',
which it binds to its socket.
This name will appear in the working directory of the program.
The routines in Figure 5b use its
socket only for sending messages.  It does not create a name for
the socket because no other process has to refer to it.  
.(z
.ft CW
.so udgramsend.c
.ft
.ce 1
Figure 5b\ \ Sending a UNIX domain datagrams
.)z
.pp
Names in the UNIX domain are path names.  Like file path names they may
be either absolute (e.g. ``/dev/imaginary'') or relative (e.g. ``socket'').
Because these names are used to allow processes to rendezvous, relative
path names can pose difficulties and should be used with care.
When a name is bound into the name space, a file (inode) is allocated in the
file system.  If
the inode is not deallocated, the name will continue to exist even after
the bound socket is closed.  This can cause subsequent runs of a program
to find that a name is unavailable, and can cause 
directories to fill up with these
objects.  The names are removed by calling \fIunlink()\fP or using
the \fIrm\fP\|(1) command.
Names in the UNIX domain are only used for rendezvous.  They are not used
for message delivery once a connection is established.  Therefore, in
contrast with the Internet domain, unbound sockets need not be (and are
not) automatically given addresses when they are connected.  
.pp
There is no established means of communicating names to interested
parties.  In the example, the program in Figure 5b gets the
name of the socket to which it will send its message through its
command line arguments.  Once a line of communication has been created,
one can send the names of additional, perhaps new, sockets over the link.
Facilities will have to be built that will make the distribution of
names less of a problem than it now is.
.b
.sh 1 "Datagrams in the Internet Domain"
.r
.(z
.ft CW
.so dgramread.c
.ft
.ce 1
Figure 6a\ \ Reading Internet domain datagrams
.)z
.pp
The examples in Figure 6a and 6b are very close to the previous example
except that the socket is in the Internet domain.
The structure of Internet domain addresses is defined in the file
\fI<netinet/in.h>\fP.
Internet addresses specify a host address (a 32-bit number)
and a delivery slot, or port, on that
machine.  These ports are managed by the system routines that implement 
a particular protocol.
Unlike UNIX domain names, Internet socket names are not entered into 
the file system and, therefore,
they do not have to be unlinked after the socket has been closed.
When a message must be sent between machines it is sent to
the protocol routine on the destination machine, which interprets the
address to determine to which socket the message should be delivered.
Several different protocols may be active on 
the same machine, but, in general, they will not communicate with one another.
As a result, different protocols are allowed to use the same port numbers.
Thus, implicitly, an Internet address is a triple including a protocol as
well as the port and machine address.
An \fIassociation\fP is a temporary or permanent specification
of a pair of communicating sockets.
An association is thus identified by the tuple
<\fIprotocol, local machine address, local port,
remote machine address, remote port\fP>.
An association may be transient when using datagram sockets;
the association actually exists during a \fIsend\fP operation.
.(z
.ft CW
.so dgramsend.c
.ft
.ce 1
Figure 6b\ \ Sending an Internet domain datagram
.)z
.pp
The protocol for a socket is chosen when the socket is created.  The 
local machine address for a socket can be any valid network address of the
machine, if it has more than one, or it can be the wildcard value
INADDR_ANY.
The wildcard value is used in the program in Figure 6a.
If a machine has several network addresses, it is likely
that messages sent to any of the addresses should be deliverable to
a socket.  This will be the case if the wildcard value has been chosen.
Note that even if the wildcard value is chosen, a program sending messages
to the named socket must specify a valid network address.  One can be willing
to receive from ``anywhere,'' but one cannot send a message ``anywhere.''
The program in Figure 6b is given the destination host name as a command
line argument.
To determine a network address to which it can send the message, it looks
up
the host address by the call to \fIgethostbyname()\fP.
The returned structure includes the host's network address,
which is copied into the structure specifying the
destination of the message.
.pp
The port number can be thought of as the number of a mailbox, into
which the protocol places one's messages.  Certain daemons, offering
certain advertised services, have reserved
or ``well-known'' port numbers.  These fall in the range
from 1 to 1023.  Higher numbers are available to general users.
Only servers need to ask for a particular number.
The system will assign an unused port number when an address
is bound to a socket.
This may happen when an explicit \fIbind\fP
call is made with a port number of 0, or
when a \fIconnect\fP or \fIsend\fP
is performed on an unbound socket.
Note that port numbers are not automatically reported back to the user.
After calling \fIbind(),\fP asking for port 0, one may call 
\fIgetsockname()\fP to discover what port was actually assigned. 
The routine \fIgetsockname()\fP
will not work for names in the UNIX domain.
.pp
The format of the socket address is specified in part by standards within the
Internet domain.  The specification includes the order of the bytes in
the address.  Because machines differ in the internal representation
they ordinarily use
to represent integers, printing out the port number as returned by 
\fIgetsockname()\fP may result in a misinterpretation.  To
print out the number, it is necessary to use the routine \fIntohs()\fP
(for \fInetwork to host: short\fP) to convert the number from the
network representation to the host's representation.  On some machines,
such as 68000-based machines, this is a null operation.  On others,
such as VAXes, this results in a swapping of bytes.  Another routine
exists to convert a short integer from the host format to the network format,
called \fIhtons()\fP; similar routines exist for long integers.
For further information, refer to the
entry for \fIbyteorder\fP in section 3 of the manual.
.b
.sh 1 "Connections"
.r
.pp
To send data between stream sockets (having communication style SOCK_STREAM),
the sockets must be connected.
Figures 7a and 7b show two programs that create such a connection.
The program in 7a is relatively simple.
To initiate a connection, this program simply creates
a stream socket, then calls \fIconnect()\fP,
specifying the address of the socket to which
it wishes its socket connected.  Provided that the target socket exists and
is prepared to handle a connection, connection will be complete,
and the program can begin to send
messages.  Messages will be delivered in order without message
boundaries, as with pipes.  The connection is destroyed when either
socket is closed (or soon thereafter).  If a process persists 
in sending messages after the connection is closed, a SIGPIPE signal 
is sent to the process by the operating system.  Unless explicit action
is taken to handle the signal (see the manual page for \fIsignal\fP
or \fIsigvec\fP),
the process will terminate and the shell
will print the message ``broken pipe.'' 
.(z
.ft CW
.so streamwrite.c
.ft
.ce 1
Figure 7a\ \ Initiating an Internet domain stream connection
.)z
.(z
.ft CW
.so streamread.c
.ft
.ce 1
Figure 7b\ \ Accepting an Internet domain stream connection
.sp 2
.ft CW
.so strchkread.c
.ft
.ce 1
Figure 7c\ \ Using select() to check for pending connections
.)z
.(z
-
.bl 5.8i
-
.\" accept.grn goes here
.sp
.ce 1
Figure 8\ \ Establishing a stream connection
.)z
.pp
Forming a connection is asymmetrical; one process, such as the
program in Figure 7a, requests a connection with a particular socket,
the other process accepts connection requests.
Before a connection can be accepted a socket must be created and an address
bound to it.  This
situation is illustrated in the top half of Figure 8.  Process 2
has created a socket and bound a port number to it.  Process 1 has created an
unnamed socket.
The address bound to process 2's socket is then made known to process 1 and, 
perhaps to several other potential communicants as well.
If there are several possible communicants,
this one socket might receive several requests for connections.
As a result, a new socket is created for each connection.  This new socket
is the endpoint for communication within this process for this connection.
A connection may be destroyed by closing the corresponding socket.
.pp
The program in Figure 7b is a rather trivial example of a server.  It 
creates a socket to which it binds a name, which it then advertises.
(In this case it prints out the socket number.)  The program then calls
\fIlisten()\fP for this socket.  
Since several clients may attempt to connect more or less
simultaneously, a queue of pending connections is maintained in the system
address space.  \fIListen()\fP
marks the socket as willing to accept connections and initializes the queue.
When a connection is requested, it is listed in the queue.  If the
queue is full, an error status may be returned to the requester.
The maximum length of this queue is specified by the second argument of
\fIlisten()\fP; the maximum length is limited by the system.  
Once the listen call has been completed, the program enters
an infinite loop.  On each pass through the loop, a new connection is
accepted and removed from the queue, and, hence, a new socket for the 
connection is created.  The bottom half of Figure 8 shows the result of
Process 1 connecting with the named socket of Process 2, and Process 2
accepting the connection.  After the connection is created, the
service, in this case printing out the messages, is performed and the
connection socket closed.  The \fIaccept()\fP
call will take a pending connection
request from the queue if one is available, or block waiting for a request.
Messages are read from the connection socket.
Reads from an active connection will normally block until data is available.
The number of bytes read is returned.  When a connection is destroyed,
the read call returns immediately.  The number of bytes returned will
be zero.
.pp
The program in Figure 7c is a slight variation on the server in Figure 7b.
It avoids blocking when there are no pending connection requests by 
calling \fIselect()\fP
to check for pending requests before calling \fIaccept().\fP
This strategy is useful when connections may be received
on more than one socket, or when data may arrive on other connected
sockets before another connection request.
.pp
The programs in Figures 9a and 9b show a program using stream communication
in the UNIX domain.  Streams in the UNIX domain can be used for this sort
of program in exactly the same way as Internet domain streams, except for
the form of the names and the restriction of the connections to a single
file system.  There are some differences, however, in the functionality of 
streams in the two domains, notably in the handling of 
\fIout-of-band\fP data (discussed briefly below).  These differences
are beyond the scope of this paper.
.(z
.ft CW
.so ustreamwrite.c
.ft
.ce 1
Figure 9a\ \ Initiating a UNIX domain stream connection
.sp 2
.ft CW
.so ustreamread.c
.ft
.ce 1
Figure 9b\ \ Accepting a UNIX domain stream connection
.)z
.b
.sh 1 "Reads, Writes, Recvs, etc."
.r
.pp
UNIX 4.3BSD has several system calls for reading and writing information.
The simplest calls are \fIread() \fP and \fIwrite().\fP \fIWrite()\fP
takes as arguments the index of a descriptor, a pointer to a buffer 
containing the data and the size of the data.
The descriptor may indicate either a file or a connected socket.  
``Connected'' can mean either a connected stream socket (as described
in Section 8) or a datagram socket for which a \fIconnect()\fP
call has provided a default destination (see the \fIconnect()\fP manual page).
\fIRead()\fP also takes a descriptor that indicates either a file or a socket.
\fIWrite()\fP requires a connected socket since no destination is 
specified in the parameters of the system call.
\fIRead()\fP can be used for either a connected or an unconnected socket.
These calls are, therefore, quite flexible and may be used to
write applications that require no assumptions about the source of
their input or the destination of their output.
There are variations on \fIread() \fP and \fIwrite()\fP
that allow the source and destination of the input and output to use
several separate buffers, while retaining the flexibility to handle
both files and sockets.  These are \fIreadv()\fP and \fI writev(),\fP
for read and write \fIvector.\fP
.pp 
It is sometimes necessary to send high priority data over a
connection that may have unread low priority data at the
other end.  For example, a user interface process may be interpreting
commands and sending them on to another process through a stream connection.
The user interface may have filled the stream with as yet unprocessed 
requests when the user types
a command to cancel all outstanding requests.
Rather than have the high priority data wait
to be processed after the low priority data, it is possible to
send it as \fIout-of-band\fP
(OOB) data.  The notification of pending OOB data results in the generation of
a SIGURG signal, if this signal has been enabled (see the manual
page for \fIsignal\fP or \fIsigvec\fP).
See [Leffler 1986] for a more complete description of the OOB mechanism.
There are a pair of calls similar to \fIread\fP and \fIwrite\fP
that allow options, including sending 
and receiving OOB information; these are \fI send()\fP
and \fIrecv().\fP
These calls are used only with sockets; specifying a descriptor for a file will
result in the return of an error status.  These calls also allow
\fIpeeking\fP at data in a stream.
That is, they allow a process to read data without removing the data from
the stream.  One use of this facility is to read ahead in a stream
to determine the size of the next item to be read.
When not using these options, these calls have the same functions as 
\fIread()\fP and \fIwrite().\fP
.pp
To send datagrams, one must be allowed to specify the destination.
The call \fIsendto()\fP
takes a destination address as an argument and is therefore used for
sending datagrams.  The call \fIrecvfrom()\fP
is often used to read datagrams, since this call returns the address
of the sender, if it is available, along with the data.
If the identity of the sender does not matter, one may use \fIread()\fP
or \fIrecv().\fP
.pp
Finally, there are a pair of calls that allow the sending and
receiving of messages from multiple buffers, when the address of the
recipient must be specified.  These are \fIsendmsg()\fP and 
\fIrecvmsg().\fP
These calls are actually quite general and have other uses,
including, in the UNIX domain, the transmission of a file descriptor from one
process to another.
.pp
The various options for reading and writing are shown in Figure 10,
together with their parameters.  The parameters for each system call
reflect the differences in function of the different calls.
In the examples given in this paper, the calls \fIread()\fP and 
\fIwrite()\fP have been used whenever possible.
.(z
.ft CW
	/*
	 * The variable descriptor may be the descriptor of either a file
	 * or of a socket.
	 */
	cc = read(descriptor, buf, nbytes)
	int cc, descriptor; char *buf; int nbytes;

	/*
	 * An iovec can include several source buffers.
	 */
	cc = readv(descriptor, iov, iovcnt)
	int cc, descriptor; struct iovec *iov; int iovcnt;

	cc = write(descriptor, buf, nbytes)
	int cc, descriptor; char *buf; int nbytes;

	cc = writev(descriptor, iovec, ioveclen)
	int cc, descriptor; struct iovec *iovec; int ioveclen;

	/*
	 * The variable ``sock'' must be the descriptor of a socket.
	 * Flags may include MSG_OOB and MSG_PEEK.
	 */
	cc = send(sock, msg, len, flags)
	int cc, sock; char *msg; int len, flags; 

	cc = sendto(sock, msg, len, flags, to, tolen)
	int cc, sock; char *msg; int len, flags;
	struct sockaddr *to; int tolen;

	cc = sendmsg(sock, msg, flags)
	int cc, sock; struct msghdr msg[]; int flags;

	cc = recv(sock, buf, len, flags)
	int cc, sock; char *buf; int len, flags;

	cc = recvfrom(sock, buf, len, flags, from, fromlen)
	int cc, sock; char *buf; int len, flags;
	struct sockaddr *from; int *fromlen;

	cc = recvmsg(sock, msg, flags)
	int cc, socket; struct msghdr msg[]; int flags;
.ft
.sp 1
.ce 1
Figure 10\ \ Varieties of read and write commands
.)z
.b
.sh 1 "Choices"
.r
.pp
This paper has presented examples of some of the forms
of communication supported by
Berkeley UNIX 4.3BSD.  These have been presented in an order chosen for
ease of presentation.  It is useful to review these options emphasizing the
factors that make each attractive.
.pp
Pipes have the advantage of portability, in that they are supported in all
UNIX systems.  They also are relatively
simple to use.  Socketpairs share this simplicity and have the additional
advantage of allowing bidirectional communication.  The major shortcoming
of these mechanisms is that they require communicating processes to be
descendants of a common process.  They do not allow intermachine communication.
.pp
The two communication domains, UNIX and Internet, allow processes with no common
ancestor to communicate.
Of the two, only the Internet domain allows
communication between machines.
This makes the Internet domain a necessary
choice for processes running on separate machines.
.pp
The choice between datagrams and stream communication is best made by
carefully considering the semantic and performance
requirements of the application.
Streams can be both advantageous and disadvantageous.  One disadvantage
is that a process is only allowed a limited number of open streams,
as there are usually only 64 entries available in the open descriptor
table.  This can cause problems if a single server must talk with a large
number of clients. 
Another is that for delivering a short message the stream setup and 
teardown time can be unnecessarily long.  Weighed against this are
the reliability built into the streams.  This will often be the
deciding factor in favor of streams.
.b
.sh 1 "What to do Next"
.r
.pp
Many of the examples presented here can serve as models for multiprocess
programs and for programs distributed across several machines.  
In developing a new multiprocess program, it is often easiest to 
first write the code to create the processes and communication paths.
After this code is debugged, the code specific to the application can
be added.
.pp
An introduction to the UNIX system and programming using UNIX system calls
can be found in [Kernighan and Pike 1984].
Further documentation of the Berkeley UNIX 4.3BSD IPC mechanisms can be 
found in [Leffler et al. 1986].
More detailed information about particular calls and protocols
is provided in sections
2, 3 and 4 of the
UNIX Programmer's Manual [CSRG 1986].
In particular the following manual pages are relevant:
.(b
.TS
l l.
creating and naming sockets	socket(2), bind(2)
establishing connections	listen(2), accept(2), connect(2)
transferring data	read(2), write(2), send(2), recv(2)
addresses	inet(4F)
protocols	tcp(4P), udp(4P).
.TE
.)b
.(b
.sp
.b
Acknowledgements
.pp
I would like to thank Sam Leffler and Mike Karels for their help in
understanding the IPC mechanisms and all the people whose comments 
have helped in writing and improving this report.
.pp
This work was sponsored by the Defense Advanced Research Projects Agency
(DoD), ARPA Order No. 4031, monitored by the Naval Electronics Systems
Command under contract No. N00039-C-0235. 
The views and conclusions contained in this document are those of the
author and should not be interpreted as representing official policies,
either expressed or implied, of the Defense Research Projects Agency
or of the US Government.
.)b
.(b
.sp
.b
References
.r
.sp
.ls 1
B.W. Kernighan & R. Pike, 1984,
.i "The UNIX Programming Environment."
Englewood Cliffs, N.J.: Prentice-Hall.
.sp
.ls 1
B.W. Kernighan & D.M. Ritchie, 1978,
.i "The C Programming Language,"
Englewood Cliffs, N.J.: Prentice-Hall.
.sp
.ls 1
S.J. Leffler, R.S. Fabry, W.N. Joy, P. Lapsley, S. Miller & C. Torek, 1986,
.i "An Advanced 4.3BSD Interprocess Communication Tutorial."
Computer Systems Research Group,
Department of Electrical Engineering and Computer Science,
University of California, Berkeley.
.sp
.ls 1
Computer Systems Research Group, 1986,
.i "UNIX Programmer's Manual, 4.3 Berkeley Software Distribution."
Computer Systems Research Group,
Department of Electrical Engineering and Computer Science,
University of California, Berkeley.
.)b
SHAR_EOF
chmod 644 'tutor.me'
cat << \SHAR_EOF > 'tutor.txt'




Introductory 4.3BSD IPC                              PS1:7-1


                   An Introductory 4.3BSD
            Interprocess Communication Tutorial


                      _S_t_u_a_r_t _S_e_c_h_r_e_s_t

              _C_o_m_p_u_t_e_r _S_c_i_e_n_c_e _R_e_s_e_a_r_c_h _G_r_o_u_p
                 _C_o_m_p_u_t_e_r _S_c_i_e_n_c_e _D_i_v_i_s_i_o_n
 _D_e_p_a_r_t_m_e_n_t _o_f _E_l_e_c_t_r_i_c_a_l _E_n_g_i_n_e_e_r_i_n_g _a_n_d _C_o_m_p_u_t_e_r _S_c_i_e_n_c_e
             _U_n_i_v_e_r_s_i_t_y _o_f _C_a_l_i_f_o_r_n_i_a, _B_e_r_k_e_l_e_y


                          _A_B_S_T_R_A_C_T


       Berkeley UNIX|- 4.3BSD offers several choices for inter-
  process communication.  To aid the programmer in  developing
  programs which are comprised of cooperating  processes,  the
  different choices are discussed and a series of example pro-
  grams are presented.  These programs demonstrate in a simple
  way  the  use  of pipes, socketpairs, sockets and the use of
  datagram and stream communication.  The intent of this docu-
  ment  is  to  present  a few simple example programs, not to
  describe the networking system in full.



_1.  _G_o_a_l_s

     Facilities for  interprocess  communication  (IPC)  and
networking  were  a  major  addition to UNIX in the Berkeley
UNIX 4.2BSD release.  These facilities required major  addi-
tions  and  some changes to the system interface.  The basic
idea of this interface is to make IPC similar to  file  I/O.
In  UNIX  a process has a set of I/O descriptors, from which
one reads and to which one writes.  Descriptors may refer to
normal  files,  to devices (including terminals), or to com-
munication channels.  The use  of  a  descriptor  has  three
phases:  its  creation, its use for reading and writing, and
its destruction.   By  using  descriptors  to  write  files,
rather than simply naming the target file in the write call,
one gains a surprising amount of  flexibility.   Often,  the
program that creates a descriptor will be different from the
program that uses the descriptor.  For example the shell can
create  a descriptor for the output of the `ls' command that
will cause the listing to appear in a file rather than on  a
terminal.   Pipes  are  another form of descriptor that have
been used in UNIX for some time.  Pipes allow  one-way  data
transmission  from one process to another; the two processes
____________________
9   |-UNIX is a trademark of AT&T Bell Laboratories.



9







PS1:7-2                              Introductory 4.3BSD IPC


and the pipe must be set up by a common ancestor.

     The use of descriptors is not  the  only  communication
interface  provided  by  UNIX.  The signal mechanism sends a
tiny amount of information from one process to another.  The
signaled  process  receives  only  the  signal type, not the
identity of the sender, and the number of  possible  signals
is small.  The signal semantics limit the flexibility of the
signaling mechanism as a means  of  interprocess  communica-
tion.

     The identification of IPC with I/O is quite  longstand-
ing in UNIX and has proved quite successful.  At first, how-
ever, IPC was limited to processes  communicating  within  a
single  machine.  With Berkeley UNIX 4.2BSD this expanded to
include IPC between machines.  This expansion  has  necessi-
tated  some  change in the way that descriptors are created.
Additionally, new possibilities for the meaning of read  and
write  have  been  admitted.   Originally  the  meanings, or
semantics, of these terms  were  fairly  simple.   When  you
wrote  something it was delivered.  When you read something,
you were blocked until the data arrived.   Other  possibili-
ties  exist,  however.  One can write without full assurance
of delivery if one  can  check  later  to  catch  occasional
failures.   Messages can be kept as discrete units or merged
into a stream. One can ask to read, but insist on not  wait-
ing  if  nothing is immediately available.  These new possi-
bilities are allowed in the Berkeley UNIX IPC interface.

     Thus Berkeley UNIX 4.3BSD offers  several  choices  for
IPC.   This  paper  presents simple examples that illustrate
some of the choices.  The reader is presumed to be  familiar
with  the C programming language [Kernighan & Ritchie 1978],
but not necessarily with the system calls of the UNIX system
or with processes and interprocess communication.  The paper
reviews the notion of a process and the types of  communica-
tion  that  are supported by Berkeley UNIX 4.3BSD.  A series
of examples are presented that create processes that commun-
icate with one another.  The programs show different ways of
establishing channels of communication.  Finally, the  calls
that  actually  transfer  data  are  reviewed.   To  clearly
present how communication can take place, the  example  pro-
grams  have been cleared of anything that might be construed
as useful work.  They can, therefore, serve  as  models  for
the  programmer  trying  to  construct  programs  which  are
comprised of cooperating processes.

_2.  _P_r_o_c_e_s_s_e_s

     A _p_r_o_g_r_a_m is both a sequence of statements and a  rough
way  of  referring  to  the computation that occurs when the
compiled statements are run.  A _p_r_o_c_e_s_s can be thought of as
a  single  line  of  control  in  a  program.  Most programs










Introductory 4.3BSD IPC                              PS1:7-3


execute some statements, go through a few loops,  branch  in
various  directions  and then end.  These are single process
programs.  Programs can also  have  a  point  where  control
splits into two independent lines, an action called _f_o_r_k_i_n_g.
In UNIX these lines can never join again.   A  call  to  the
system  routine  _f_o_r_k(),  causes  a process to split in this
way.  The result  of  this  call  is  that  two  independent
processes  will be running, executing exactly the same code.
Memory values will be the same for all values set before the
fork, but, subsequently, each version will be able to change
only the value of its own copy of each variable.  Initially,
the  only  difference  between  the  two  will  be the value
returned by _f_o_r_k().  The parent will receive  a  process  id
for  the  child,  the  child  will receive a zero.  Calls to
_f_o_r_k(), therefore, typically precede, or are included in, an
if-statement.

     A process views  the  rest  of  the  system  through  a
private table of descriptors.  The descriptors can represent
open files or sockets  (sockets  are  communication  objects
that  will be discussed below).  Descriptors are referred to
by their index  numbers  in  the  table.   The  first  three
descriptors are often known by special names,  _s_t_d_i_n, _s_t_d_o_u_t
and _s_t_d_e_r_r.  These are the standard input, output and error.
When  a process forks, its descriptor table is copied to the
child.  Thus, if the parent's standard input is being  taken
from a terminal (devices are also treated as files in UNIX),
the child's input will be  taken  from  the  same  terminal.
Whoever reads first will get the input.  If, before forking,
the parent changes its standard input so that it is  reading
from  a new file, the child will take its input from the new
file.  It is also possible to  take  input  from  a  socket,
rather than from a file.

_3.  _P_i_p_e_s

     Most users of UNIX know that they can pipe  the  output
of  a  program ``prog1'' to the input of another, ``prog2,''
by typing the command ``_p_r_o_g_1  |  _p_r_o_g_2.''  This  is  called
``piping''  the output of one program to another because the
mechanism used to transfer the  output  is  called  a  pipe.
When  the  user  types a command, the command is read by the
shell, which decides how to execute it.  If the  command  is
simple,  for  example, ``_p_r_o_g_1,'' the shell forks a process,
which executes the program, prog1, and then dies.  The shell
waits  for  this  termination  and then prompts for the next
command.  If the command is a compound  command,  ``_p_r_o_g_1  |
_p_r_o_g_2,''  the  shell  creates  two  processes connected by a
pipe. One process runs the program, prog1,  the  other  runs
prog2.  The pipe is an I/O mechanism with two ends, or sock-
ets.  Data that is written into one socket can be read  from
the other.
9

9







PS1:7-4                              Introductory 4.3BSD IPC



/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)pipe.c      6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <stdio.h>

#define DATA "Bright star, would I were steadfast as thou art . . ."

/*
 * This program creates a pipe, then forks.  The child communicates to the
 * parent over the pipe. Notice that a pipe is a one-way communications
 * device.  I can write to the output socket (sockets[1], the second socket
 * of the array returned by pipe()) and read from the input socket
 * (sockets[0]), but not vice versa.
 */

main()
{
        int sockets[2], child;

        /* Create a pipe */
        if (pipe(sockets) < 0) {
                perror("opening stream socket pair");
                exit(10);
        }

        if ((child = fork()) == -1)
                perror("fork");
        else if (child) {
                char buf[1024];










Introductory 4.3BSD IPC                              PS1:7-5


                /* This is still the parent.  It reads the child's message. */
                close(sockets[1]);
                if (read(sockets[0], buf, 1024) < 0)
                        perror("reading message");
                printf("-->%s\n", buf);
                close(sockets[0]);
        } else {
                /* This is the child.  It writes a message to its parent. */
                close(sockets[0]);
                if (write(sockets[1], DATA, sizeof(DATA)) < 0)
                        perror("writing message");
                close(sockets[1]);
        }
}
                  Figure 1  Use of a pipe

     Since a program specifies its input and output only  by
the  descriptor  table indices, which appear as variables or
constants, the input source and output  destination  can  be
changed  without changing the text of the program.  It is in
this way that the shell is able to  set  up  pipes.   Before
executing prog1, the process can close whatever is at _s_t_d_o_u_t
and replace it with one end of a pipe.  Similarly, the  pro-
cess that will execute prog2 can substitute the opposite end
of the pipe for _s_t_d_i_n.

     Let us now examine a program that creates  a  pipe  for
communication  between  its  child and itself (Figure 1).  A
pipe is created by a parent process, which then forks.  When
a  process  forks,  the  parent's descriptor table is copied
into the child's.

     In Figure 1, the parent process makes  a  call  to  the
system  routine  _p_i_p_e().   This  routine  creates a pipe and
places descriptors for the sockets for the two ends  of  the
pipe in the process's descriptor table.  _P_i_p_e() is passed an
array into which it places the index numbers of the  sockets
it  created.   The  two ends are not equivalent.  The socket
whose index is returned in the low  word  of  the  array  is
opened for reading only, while the socket in the high end is
opened only for writing.  This corresponds to the fact  that
the  standard  input  is the first descriptor of a process's
descriptor table and the  standard  output  is  the  second.
After  creating  the pipe, the parent creates the child with
which it will share the pipe by calling  _f_o_r_k().   Figure  2
illustrates  the  effect  of  a  fork.  The parent process's
descriptor table points to both ends of the pipe.  After the
fork,  both  parent's and child's descriptor tables point to
the pipe.  The child can then use the pipe to send a message
to the parent.

     Just what is a pipe?  It  is  a  one-way  communication
mechanism, with one end opened for reading and the other end










PS1:7-6                              Introductory 4.3BSD IPC



-



































-

     Figure 2  Sharing a pipe between parent and child

for writing.  Therefore, parent and child need to  agree  on
which  way  to  turn  the  pipe, from parent to child or the
other way around.  Using the  same  pipe  for  communication
both  from parent to child and from child to parent would be
possible (since  both  processes  have  references  to  both
ends), but very complicated.  If the parent and child are to
have a two-way conversation, the parent creates  two  pipes,
one  for  use  in each direction.  (In accordance with their
plans, both parent and child in the example above close  the
socket  that  they  will  not  use.  It is not required that
unused descriptors be closed, but it is  good  practice.)  A
pipe  is also a _s_t_r_e_a_m communication mechanism; that is, all










Introductory 4.3BSD IPC                              PS1:7-7


messages sent through the pipe are placed in order and reli-
ably  delivered.   When the reader asks for a certain number
of bytes from this stream, he is given as many bytes as  are
available,  up to the amount of the request. Note that these
bytes may have come from the same call to  _w_r_i_t_e()  or  from
several calls to _w_r_i_t_e() which were concatenated.

_4.  _S_o_c_k_e_t_p_a_i_r_s

     Berkeley UNIX 4.3BSD provides a  slight  generalization
of pipes.  A pipe is a pair of connected sockets for one-way
stream communication.  One may obtain a  pair  of  connected
sockets for two-way stream communication by calling the rou-
tine _s_o_c_k_e_t_p_a_i_r().  The program in Figure  3  calls  _s_o_c_k_e_t_-
_p_a_i_r()  to  create  such a connection.  The program uses the
link for communication in both  directions.   Since  socket-
pairs are an extension of pipes, their use resembles that of
pipes. Figure 4 illustrates the result of a fork following a
call to _s_o_c_k_e_t_p_a_i_r().

     _S_o_c_k_e_t_p_a_i_r() takes as arguments a  specification  of  a
domain,  a style of communication, and a protocol. These are
the parameters shown in the example.  Domains and  protocols
will be discussed in the next section.  Briefly, a domain is
a space of names that may be bound to  sockets  and  implies
certain other conventions.  Currently, socketpairs have only
been implemented for one domain,  called  the  UNIX  domain.
The  UNIX domain uses UNIX path names for naming sockets. It
only  allows  communication  between  sockets  on  the  same
machine.

     Note  that  the   header   files   <_s_y_s/_s_o_c_k_e_t._h>   and
<_s_y_s/_t_y_p_e_s._h>.  are required in this program.  The constants
AF_UNIX and SOCK_STREAM are defined in <_s_y_s/_s_o_c_k_e_t._h>, which
in  turn  requires  the  file  <_s_y_s/_t_y_p_e_s._h> for some of its
definitions.

_5.  _D_o_m_a_i_n_s _a_n_d _P_r_o_t_o_c_o_l_s

     Pipes and socketpairs are a simple solution for commun-
icating   between  a  parent  and  child  or  between  child
processes.  What if we wanted to have processes that have no
common  ancestor with whom to set up communication?  Neither
standard UNIX pipes nor socketpairs  are  the  answer  here,
since  both  mechanisms  require a common ancestor to set up
the communication.  We would  like  to  have  two  processes
separately  create  sockets  and  then  have  messages  sent
between them.  This is often  the  case  when  providing  or
using  a  service in the system.  This is also the case when
the communicating processes are on  separate  machines.   In
Berkeley UNIX 4.3BSD one can create individual sockets, give
them names and send messages between them.
9

9







PS1:7-8                              Introductory 4.3BSD IPC



/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)socketpair.c        6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>

#define DATA1 "In Xanadu, did Kublai Khan . . ."
#define DATA2 "A stately pleasure dome decree . . ."

/*
 * This program creates a pair of connected sockets then forks and
 * communicates over them.  This is very similar to communication with pipes,
 * however, socketpairs are two-way communications objects. Therefore I can
 * send messages in both directions.
 */

main()
{
        int sockets[2], child;
        char buf[1024];

        if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
                perror("opening stream socket pair");
                exit(1);
        }

        if ((child = fork()) == -1)
                perror("fork");










Introductory 4.3BSD IPC                              PS1:7-9


        else if (child) {       /* This is the parent. */
                close(sockets[0]);
                if (read(sockets[1], buf, 1024, 0) < 0)
                        perror("reading stream message");
                printf("-->%s\n", buf);
                if (write(sockets[1], DATA2, sizeof(DATA2)) < 0)
                        perror("writing stream message");
                close(sockets[1]);
        } else {                /* This is the child. */
                close(sockets[1]);
                if (write(sockets[0], DATA1, sizeof(DATA1)) < 0)
                        perror("writing stream message");
                if (read(sockets[0], buf, 1024, 0) < 0)
                        perror("reading stream message");
                printf("-->%s\n", buf);
                close(sockets[0]);
        }
}
               Figure 3  Use of a socketpair

































9

9







PS1:7-10                             Introductory 4.3BSD IPC


-



































-

  Figure 4  Sharing a socketpair between parent and child

     Sockets created by  different  programs  use  names  to
refer  to  one  another;  names generally must be translated
into addresses for use.  The space from which an address  is
drawn is referred to as a _d_o_m_a_i_n.  There are several domains
for sockets.  Two that will be used in the examples here are
the  UNIX  domain  (or AF_UNIX, for Address Format UNIX) and
the Internet domain (or AF_INET).  UNIX  domain  IPC  is  an
experimental  facility  in  4.2BSD  and 4.3BSD.  In the UNIX
domain, a socket is given a path name within the file system
name  space.   A  file system node is created for the socket
and other processes may then refer to the socket  by  giving
the  proper  pathname.   UNIX domain names, therefore, allow
communication between any two processes  that  work  in  the










Introductory 4.3BSD IPC                             PS1:7-11


same file system.  The Internet domain is the UNIX implemen-
tation of the DARPA Internet standard protocols  IP/TCP/UDP.
Addresses  in  the Internet domain consist of a machine net-
work address and  an  identifying  number,  called  a  port.
Internet domain names allow communication between machines.

     Communication  follows   some   particular   ``style.''
Currently,  communication  is  either through a _s_t_r_e_a_m or by
_d_a_t_a_g_r_a_m.   Stream  communication  implies  several  things.
Communication  takes  place  across a connection between two
sockets.  The communication is reliable, error-free, and, as
in  pipes,  no  message  boundaries are kept. Reading from a
stream may result in reading  the  data  sent  from  one  or
several  calls  to  _w_r_i_t_e()  or only part of the data from a
single call, if there is not enough room for the entire mes-
sage,  or  if not all the data from a large message has been
transferred.  The protocol implementing such  a  style  will
retransmit  messages  received  with  errors.  It  will also
return error messages if one tries to send a  message  after
the connection has been broken.  Datagram communication does
not use connections.  Each message  is  addressed  individu-
ally.   If  the  address  is  correct,  it will generally be
received, although this is not guaranteed.  Often  datagrams
are used for requests that require a response from the reci-
pient.  If no response arrives in  a  reasonable  amount  of
time,  the  request  is  repeated.  The individual datagrams
will be kept separate when they are read, that  is,  message
boundaries are preserved.

     The difference in performance between the two styles of
communication  is  generally less important than the differ-
ence in semantics.  The performance gain that one might find
in  using  datagrams  must  be weighed against the increased
complexity of the program, which  must  now  concern  itself
with  lost  or  out of order messages.  If lost messages may
simply be ignored, the quantity of traffic  may  be  a  con-
sideration.  The  expense of setting up a connection is best
justified by frequent use of the connection.  Since the per-
formance  of a protocol changes as it is tuned for different
situations, it is best to seek the most up-to-date  informa-
tion  when making choices for a program in which performance
is crucial.

     A protocol is a set of rules, data formats and  conven-
tions  that  regulate  the transfer of data between partici-
pants in the communication.  In general, there is one proto-
col  for  each  socket  type (stream, datagram, etc.) within
each domain.  The code  that  implements  a  protocol  keeps
track  of  the names that are bound to sockets, sets up con-
nections and transfers data between sockets, perhaps sending
the  data  across  a network.  This code also keeps track of
the names that are bound to sockets.   It  is  possible  for
several  protocols,  differing only in low level details, to










PS1:7-12                             Introductory 4.3BSD IPC


implement the same style of communication within a  particu-
lar  domain.  Although it is possible to select which proto-
col should be used, for nearly all uses it is sufficient  to
request  the default protocol.  This has been done in all of
the example programs.

     One specifies the  domain,  style  and  protocol  of  a
socket  when  it  is created.  For example, in Figure 5a the
call to _s_o_c_k_e_t() causes the creation of  a  datagram  socket
with the default protocol in the UNIX domain.

_6.  _D_a_t_a_g_r_a_m_s _i_n _t_h_e _U_N_I_X _D_o_m_a_i_n

     Let us now look at two  programs  that  create  sockets
separately.   The programs in Figures 5a and 5b use datagram
communication rather than a stream. The  structure  used  to
name  UNIX domain sockets is defined in the file <_s_y_s/_u_n._h>.
The definition has also been included  in  the  example  for
clarity.

     Each program creates a socket with a call to  _s_o_c_k_e_t().
These  sockets are in the UNIX domain.  Once a name has been
decided upon it is attached to a socket by the  system  call
_b_i_n_d().   The program in Figure 5a uses the name ``socket'',
which it binds to its socket.  This name will appear in  the
working directory of the program.  The routines in Figure 5b
use its socket only  for  sending  messages.   It  does  not
create a name for the socket because no other process has to
refer to it.

     Names in the UNIX domain are  path  names.   Like  file
path    names    they   may   be   either   absolute   (e.g.
``/dev/imaginary'') or relative (e.g. ``socket'').   Because
these names are used to allow processes to rendezvous, rela-
tive path names can pose difficulties  and  should  be  used
with care.  When a name is bound into the name space, a file
(inode) is allocated in the file system.  If  the  inode  is
not  deallocated, the name will continue to exist even after
the bound socket is closed.  This can cause subsequent  runs
of  a  program  to  find that a name is unavailable, and can
cause directories to fill up with these objects.  The  names
are  removed by calling _u_n_l_i_n_k() or using the _r_m(1) command.
Names in the UNIX domain are only used for rendezvous.  They
are not used for message delivery once a connection is esta-
blished.  Therefore, in contrast with the  Internet  domain,
unbound  sockets  need  not  be  (and are not) automatically
given addresses when they are connected.

     There is no established means of communicating names to
interested  parties.   In the example, the program in Figure
5b gets the name of the socket to which  it  will  send  its
message  through its command line arguments.  Once a line of
communication has been created, one can send  the  names  of










Introductory 4.3BSD IPC                             PS1:7-13



/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)udgramread.c        6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

/*
 * In the included file <sys/un.h> a sockaddr_un is defined as follows
 * struct sockaddr_un {
 *      short   sun_family;
 *      char    sun_path[108];
 * };
 */

#include <stdio.h>

#define NAME "socket"

/*
 * This program creates a UNIX domain datagram socket, binds a name to it,
 * then reads from the socket.
 */
main()
{
        int sock, length;
        struct sockaddr_un name;
        char buf[1024];
9

9







PS1:7-14                             Introductory 4.3BSD IPC


        /* Create socket from which to read. */
        sock = socket(AF_UNIX, SOCK_DGRAM, 0);
        if (sock < 0) {
                perror("opening datagram socket");
                exit(1);
        }
        /* Create name. */
        name.sun_family = AF_UNIX;
        strcpy(name.sun_path, NAME);
        if (bind(sock, &name, sizeof(struct sockaddr_un))) {
                perror("binding name to datagram socket");
                exit(1);
        }
        printf("socket -->%s\n", NAME);
        /* Read from the socket */
        if (read(sock, buf, 1024) < 0)
                perror("receiving datagram packet");
        printf("-->%s\n", buf);
        close(sock);
        unlink(NAME);
}
          Figure 5a  Reading UNIX domain datagrams






























9

9







Introductory 4.3BSD IPC                             PS1:7-15


/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)udgramsend.c        6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define DATA "The sea is calm tonight, the tide is full . . ."

/*
 * Here I send a datagram to a receiver whose name I get from the command
 * line arguments.  The form of the command line is udgramsend pathname
 */

main(argc, argv)
        int argc;
        char *argv[];
{
        int sock;
        struct sockaddr_un name;

        /* Create socket on which to send. */
        sock = socket(AF_UNIX, SOCK_DGRAM, 0);
        if (sock < 0) {
                perror("opening datagram socket");
                exit(1);
        }
        /* Construct name of socket to send to. */
        name.sun_family = AF_UNIX;










PS1:7-16                             Introductory 4.3BSD IPC


        strcpy(name.sun_path, argv[1]);
        /* Send message. */
        if (sendto(sock, DATA, sizeof(DATA), 0,
            &name, sizeof(struct sockaddr_un)) < 0) {
                perror("sending datagram message");
        }
        close(sock);
}
         Figure 5b  Sending a UNIX domain datagrams

additional, perhaps new, sockets over the link.   Facilities
will  have  to  be  built that will make the distribution of
names less of a problem than it now is.

_7.  _D_a_t_a_g_r_a_m_s _i_n _t_h_e _I_n_t_e_r_n_e_t _D_o_m_a_i_n

     The examples in Figure 6a and 6b are very close to  the
previous  example  except that the socket is in the Internet
domain.  The  structure  of  Internet  domain  addresses  is
defined  in  the  file  <_n_e_t_i_n_e_t/_i_n._h>.   Internet addresses
specify a host address (a  32-bit  number)  and  a  delivery
slot,  or port, on that machine.  These ports are managed by
the system routines that implement  a  particular  protocol.
Unlike  UNIX  domain  names,  Internet  socket names are not
entered into the file system and,  therefore,  they  do  not
have  to be unlinked after the socket has been closed.  When
a message must be sent between machines it is  sent  to  the
protocol  routine  on  the destination machine, which inter-
prets the address to determine to which socket  the  message
should  be  delivered.   Several  different protocols may be
active on the same machine, but, in general, they  will  not
communicate with one another.  As a result, different proto-
cols are allowed to use the same port numbers.  Thus, impli-
citly,  an Internet address is a triple including a protocol
as well as the port and machine address.  An _a_s_s_o_c_i_a_t_i_o_n  is
a temporary or permanent specification of a pair of communi-
cating sockets.  An association is thus  identified  by  the
tuple  <_p_r_o_t_o_c_o_l,  _l_o_c_a_l _m_a_c_h_i_n_e _a_d_d_r_e_s_s, _l_o_c_a_l _p_o_r_t, _r_e_m_o_t_e
_m_a_c_h_i_n_e _a_d_d_r_e_s_s, _r_e_m_o_t_e _p_o_r_t>.  An association may be  tran-
sient  when using datagram sockets; the association actually
exists during a _s_e_n_d operation.

     The protocol for a socket is chosen when the socket  is
created.   The local machine address for a socket can be any
valid network address of the machine, if it  has  more  than
one,  or it can be the wildcard value INADDR_ANY.  The wild-
card value is used in  the  program  in  Figure  6a.   If  a
machine  has  several  network  addresses, it is likely that
messages sent to any of the addresses should be  deliverable
to  a  socket.   This will be the case if the wildcard value
has been chosen.  Note that even if the  wildcard  value  is
chosen,  a program sending messages to the named socket must
specify a valid network address.   One  can  be  willing  to










Introductory 4.3BSD IPC                             PS1:7-17



/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)dgramread.c 6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>

/*
 * In the included file <netinet/in.h> a sockaddr_in is defined as follows:
 * struct sockaddr_in {
 *      short   sin_family;
 *      u_short sin_port;
 *      struct in_addr sin_addr;
 *      char    sin_zero[8];
 * };
 *
 * This program creates a datagram socket, binds a name to it, then reads
 * from the socket.
 */
main()
{
        int sock, length;
        struct sockaddr_in name;
        char buf[1024];

        /* Create socket from which to read. */
        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock < 0) {










PS1:7-18                             Introductory 4.3BSD IPC


                perror("opening datagram socket");
                exit(1);
        }
        /* Create name with wildcards. */
        name.sin_family = AF_INET;
        name.sin_addr.s_addr = INADDR_ANY;
        name.sin_port = 0;
        if (bind(sock, &name, sizeof(name))) {
                perror("binding datagram socket");
                exit(1);
        }
        /* Find assigned port value and print it out. */
        length = sizeof(name);
        if (getsockname(sock, &name, &length)) {
                perror("getting socket name");
                exit(1);
        }
        printf("Socket has port #%d\n", ntohs(name.sin_port));
        /* Read from the socket */
        if (read(sock, buf, 1024) < 0)
                perror("receiving datagram packet");
        printf("-->%s\n", buf);
        close(sock);
}
        Figure 6a  Reading Internet domain datagrams



























9

9







Introductory 4.3BSD IPC                             PS1:7-19


/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)dgramsend.c 6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

#define DATA "The sea is calm tonight, the tide is full . . ."

/*
 * Here I send a datagram to a receiver whose name I get from the command
 * line arguments.  The form of the command line is dgramsend hostname
 * portnumber
 */

main(argc, argv)
        int argc;
        char *argv[];
{
        int sock;
        struct sockaddr_in name;
        struct hostent *hp, *gethostbyname();

        /* Create socket on which to send. */
        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock < 0) {
                perror("opening datagram socket");
                exit(1);










PS1:7-20                             Introductory 4.3BSD IPC


        }
        /*
         * Construct name, with no wildcards, of the socket to send to.
         * Getnostbyname() returns a structure including the network address
         * of the specified host.  The port number is taken from the command
         * line.
         */
        hp = gethostbyname(argv[1]);
        if (hp == 0) {
                fprintf(stderr, "%s: unknown host0, argv[1]);
                exit(2);
        }
        bcopy(hp->h_addr, &name.sin_addr, hp->h_length);
        name.sin_family = AF_INET;
        name.sin_port = htons(atoi(argv[2]));
        /* Send message. */
        if (sendto(sock, DATA, sizeof(DATA), 0, &name, sizeof(name)) < 0)
                perror("sending datagram message");
        close(sock);
}
       Figure 6b  Sending an Internet domain datagram

receive from ``anywhere,'' but one  cannot  send  a  message
``anywhere.'' The program in Figure 6b is given the destina-
tion host name as a command line argument.  To  determine  a
network  address  to which it can send the message, it looks
up the host address by the  call  to  _g_e_t_h_o_s_t_b_y_n_a_m_e().   The
returned  structure  includes  the  host's  network address,
which is copied into the structure specifying  the  destina-
tion of the message.

     The port number can be thought of as the  number  of  a
mailbox,  into  which  the  protocol  places one's messages.
Certain daemons, offering certain advertised services,  have
reserved  or ``well-known'' port numbers.  These fall in the
range from 1 to 1023.  Higher numbers are available to  gen-
eral  users.   Only  servers  need  to  ask for a particular
number.  The system will assign an unused port  number  when
an  address  is  bound to a socket.  This may happen when an
explicit _b_i_n_d call is made with a port number of 0, or  when
a  _c_o_n_n_e_c_t  or _s_e_n_d is performed on an unbound socket.  Note
that port numbers are not automatically reported back to the
user.  After calling _b_i_n_d(), asking for port 0, one may call
_g_e_t_s_o_c_k_n_a_m_e() to discover what port was  actually  assigned.
The  routine  _g_e_t_s_o_c_k_n_a_m_e()  will  not work for names in the
UNIX domain.

     The format of the socket address is specified  in  part
by  standards within the Internet domain.  The specification
includes the order of the bytes  in  the  address.   Because
machines  differ  in  the internal representation they ordi-
narily use to represent  integers,  printing  out  the  port
number   as  returned  by  _g_e_t_s_o_c_k_n_a_m_e()  may  result  in  a










Introductory 4.3BSD IPC                             PS1:7-21


misinterpretation.  To print out the number, it is necessary
to  use  the routine _n_t_o_h_s() (for _n_e_t_w_o_r_k _t_o _h_o_s_t: _s_h_o_r_t) to
convert the number from the network  representation  to  the
host's  representation.   On  some  machines, such as 68000-
based machines, this is a null operation.  On  others,  such
as VAXes, this results in a swapping of bytes.  Another rou-
tine exists to convert a short integer from the host  format
to  the  network  format,  called  _h_t_o_n_s(); similar routines
exist for long integers.  For further information, refer  to
the entry for _b_y_t_e_o_r_d_e_r in section 3 of the manual.

_8.  _C_o_n_n_e_c_t_i_o_n_s

     To send data between stream sockets (having  communica-
tion  style  SOCK_STREAM),  the  sockets  must be connected.
Figures 7a and 7b show two programs that create such a  con-
nection.   The  program in 7a is relatively simple.  To ini-
tiate a connection, this program  simply  creates  a  stream
socket,  then calls _c_o_n_n_e_c_t(), specifying the address of the
socket to which it wishes its  socket  connected.   Provided
that  the  target  socket exists and is prepared to handle a
connection, connection will be complete, and the program can
begin to send messages.  Messages will be delivered in order
without message boundaries, as with pipes.   The  connection
is   destroyed   when  either  socket  is  closed  (or  soon
thereafter).  If a  process  persists  in  sending  messages
after  the connection is closed, a SIGPIPE signal is sent to
the process by the operating system.  Unless explicit action
is  taken to handle the signal (see the manual page for _s_i_g_-
_n_a_l or _s_i_g_v_e_c), the process will  terminate  and  the  shell
will print the message ``broken pipe.''

     Forming a connection is asymmetrical; one process, such
as  the  program  in Figure 7a, requests a connection with a
particular socket,  the  other  process  accepts  connection
requests.  Before a connection can be accepted a socket must
be created and an address bound to it.   This  situation  is
illustrated  in  the  top  half  of Figure 8.  Process 2 has
created a socket and bound a port number to it.   Process  1
has created an unnamed socket.  The address bound to process
2's socket is then made known to process 1 and,  perhaps  to
several  other potential communicants as well.  If there are
several possible communicants, this one socket might receive
several requests for connections.  As a result, a new socket
is created for each connection.  This new socket is the end-
point for communication within this process for this connec-
tion.   A  connection  may  be  destroyed  by  closing   the
corresponding socket.

     The program in Figure 7b is a rather trivial example of
a  server.   It  creates  a socket to which it binds a name,
which it then advertises.  (In this case it prints  out  the
socket  number.)   The  program then calls _l_i_s_t_e_n() for this










PS1:7-22                             Introductory 4.3BSD IPC



/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)streamwrite.c       6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>

#define DATA "Half a league, half a league . . ."

/*
 * This program creates a socket and initiates a connection with the socket
 * given in the command line.  One message is sent over the connection and
 * then the socket is closed, ending the connection. The form of the command
 * line is streamwrite hostname portnumber
 */

main(argc, argv)
        int argc;
        char *argv[];
{
        int sock;
        struct sockaddr_in server;
        struct hostent *hp, *gethostbyname();
        char buf[1024];

        /* Create socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);










Introductory 4.3BSD IPC                             PS1:7-23


        if (sock < 0) {
                perror("opening stream socket");
                exit(1);
        }
        /* Connect socket using name specified by command line. */
        server.sin_family = AF_INET;
        hp = gethostbyname(argv[1]);
        if (hp == 0) {
                fprintf(stderr, "%s: unknown host0, argv[1]);
                exit(2);
        }
        bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
        server.sin_port = htons(atoi(argv[2]));

        if (connect(sock, &server, sizeof(server)) < 0) {
                perror("connecting stream socket");
                exit(1);
        }
        if (write(sock, DATA, sizeof(DATA)) < 0)
                perror("writing on stream socket");
        close(sock);
}
 Figure 7a  Initiating an Internet domain stream connection





























9

9







PS1:7-24                             Introductory 4.3BSD IPC


/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)streamread.c        6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define TRUE 1

/*
 * This program creates a socket and then begins an infinite loop. Each time
 * through the loop it accepts a connection and prints out messages from it.
 * When the connection breaks, or a termination message comes through, the
 * program accepts a new connection.
 */

main()
{
        int sock, length;
        struct sockaddr_in server;
        int msgsock;
        char buf[1024];
        int rval;
        int i;

        /* Create socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
                perror("opening stream socket");










Introductory 4.3BSD IPC                             PS1:7-25


                exit(1);
        }
        /* Name socket using wildcards */
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = 0;
        if (bind(sock, &server, sizeof(server))) {
                perror("binding stream socket");
                exit(1);
        }
        /* Find out assigned port number and print it out */
        length = sizeof(server);
        if (getsockname(sock, &server, &length)) {
                perror("getting socket name");
                exit(1);
        }
        printf("Socket has port #%d\n", ntohs(server.sin_port));

        /* Start accepting connections */
        listen(sock, 5);
        do {
                msgsock = accept(sock, 0, 0);
                if (msgsock == -1)
                        perror("accept");
                else do {
                        bzero(buf, sizeof(buf));
                        if ((rval = read(msgsock, buf, 1024)) < 0)
                                perror("reading stream message");
                        i = 0;
                        if (rval == 0)
                                printf("Ending connection\n");
                        else
                                printf("-->%s\n", buf);
                } while (rval != 0);
                close(msgsock);
        } while (TRUE);
        /*
         * Since this program has an infinite loop, the socket "sock" is
         * never explicitly closed.  However, all sockets will be closed
         * automatically when a process is killed or terminates normally.
         */
}
 Figure 7b  Accepting an Internet domain stream connection


/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such










PS1:7-26                             Introductory 4.3BSD IPC


 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)strchkread.c        6.3 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define TRUE 1

/*
 * This program uses select() to check that someone is trying to connect
 * before calling accept().
 */

main()
{
        int sock, length;
        struct sockaddr_in server;
        int msgsock;
        char buf[1024];
        int rval;
        fd_set ready;
        struct timeval to;

        /* Create socket */
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
                perror("opening stream socket");
                exit(1);
        }
        /* Name socket using wildcards */
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = INADDR_ANY;
        server.sin_port = 0;
        if (bind(sock, &server, sizeof(server))) {
                perror("binding stream socket");










Introductory 4.3BSD IPC                             PS1:7-27


                exit(1);
        }
        /* Find out assigned port number and print it out */
        length = sizeof(server);
        if (getsockname(sock, &server, &length)) {
                perror("getting socket name");
                exit(1);
        }
        printf("Socket has port #%d\n", ntohs(server.sin_port));

        /* Start accepting connections */
        listen(sock, 5);
        do {
                FD_ZERO(&ready);
                FD_SET(sock, &ready);
                to.tv_sec = 5;
                if (select(sock + 1, &ready, 0, 0, &to) < 0) {
                        perror("select");
                        continue;
                }
                if (FD_ISSET(sock, &ready)) {
                        msgsock = accept(sock, (struct sockaddr *)0, (int *)0);
                        if (msgsock == -1)
                                perror("accept");
                        else do {
                                bzero(buf, sizeof(buf));
                                if ((rval = read(msgsock, buf, 1024)) < 0)
                                        perror("reading stream message");
                                else if (rval == 0)
                                        printf("Ending connection\n");
                                else
                                        printf("-->%s\n", buf);
                        } while (rval > 0);
                        close(msgsock);
                } else
                        printf("Do something else\n");
        } while (TRUE);
}
 Figure 7c  Using select() to check for pending connections













9

9







PS1:7-28                             Introductory 4.3BSD IPC


-



































-

         Figure 8  Establishing a stream connection

socket. Since several clients may attempt to connect more or
less simultaneously, a queue of pending connections is main-
tained in the system  address  space.   _L_i_s_t_e_n()  marks  the
socket  as willing to accept connections and initializes the
queue.  When a connection is requested, it is listed in  the
queue.   If  the  queue  is  full,  an  error  status may be
returned to the requester.  The maximum length of this queue
is specified by the second argument of _l_i_s_t_e_n(); the maximum
length is limited by the system. Once the  listen  call  has
been  completed,  the  program  enters an infinite loop.  On
each pass through the loop, a new connection is accepted and
removed  from  the  queue,  and, hence, a new socket for the
connection is created.  The bottom half of  Figure  8  shows










Introductory 4.3BSD IPC                             PS1:7-29


the  result of Process 1 connecting with the named socket of
Process 2, and Process 2 accepting  the  connection.   After
the  connection is created, the service, in this case print-
ing out the messages, is performed and the connection socket
closed.   The  _a_c_c_e_p_t()  call will take a pending connection
request from the queue if one is available, or block waiting
for  a  request.   Messages  are  read  from  the connection
socket.  Reads from an active connection will normally block
until  data  is  available.   The  number  of  bytes read is
returned.  When a connection is  destroyed,  the  read  call
returns  immediately.   The number of bytes returned will be
zero.

     The program in Figure 7c is a slight variation  on  the
server  in  Figure 7b.  It avoids blocking when there are no
pending connection requests by calling _s_e_l_e_c_t() to check for
pending  requests before calling _a_c_c_e_p_t().  This strategy is
useful when connections may be received  on  more  than  one
socket,  or  when data may arrive on other connected sockets
before another connection request.

     The programs in Figures 9a and 9b show a program  using
stream  communication  in  the  UNIX domain.  Streams in the
UNIX domain can be used for this sort of program in  exactly
the same way as Internet domain streams, except for the form
of the names and the restriction of  the  connections  to  a
single file system.  There are some differences, however, in
the functionality of streams in the two domains, notably  in
the  handling of _o_u_t-_o_f-_b_a_n_d data (discussed briefly below).
These differences are beyond the scope of this paper.

_9.  _R_e_a_d_s, _W_r_i_t_e_s, _R_e_c_v_s, _e_t_c.

     UNIX 4.3BSD has several system calls  for  reading  and
writing  information.   The  simplest  calls are _r_e_a_d()  and
_w_r_i_t_e(). _W_r_i_t_e() takes as arguments the index of a  descrip-
tor,  a pointer to a buffer containing the data and the size
of the data.  The descriptor may indicate either a file or a
connected  socket. ``Connected'' can mean either a connected
stream socket (as described in  Section  8)  or  a  datagram
socket  for  which  a  _c_o_n_n_e_c_t() call has provided a default
destination (see the _c_o_n_n_e_c_t() manual  page).   _R_e_a_d()  also
takes a descriptor that indicates either a file or a socket.
_W_r_i_t_e() requires a connected socket since no destination  is
specified  in the parameters of the system call.  _R_e_a_d() can
be used for either a connected  or  an  unconnected  socket.
These  calls  are, therefore, quite flexible and may be used
to write applications that require no assumptions about  the
source  of  their  input or the destination of their output.
There are variations on _r_e_a_d()  and _w_r_i_t_e() that  allow  the
source  and  destination  of  the  input  and  output to use
several separate buffers, while retaining the flexibility to
handle  both  files  and  sockets.   These  are  _r_e_a_d_v() and










PS1:7-30                             Introductory 4.3BSD IPC



/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)ustreamwrite.c      6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define DATA "Half a league, half a league . . ."

/*
 * This program connects to the socket named in the command line and sends a
 * one line message to that socket. The form of the command line is
 * ustreamwrite pathname
 */
main(argc, argv)
        int argc;
        char *argv[];
{
        int sock;
        struct sockaddr_un server;
        char buf[1024];

        /* Create socket */
        sock = socket(AF_UNIX, SOCK_STREAM, 0);
        if (sock < 0) {
                perror("opening stream socket");
                exit(1);
        }










Introductory 4.3BSD IPC                             PS1:7-31


        /* Connect socket using name specified by command line. */
        server.sun_family = AF_UNIX;
        strcpy(server.sun_path, argv[1]);

        if (connect(sock, &server, sizeof(struct sockaddr_un)) < 0) {
                close(sock);
                perror("connecting stream socket");
                exit(1);
        }
        if (write(sock, DATA, sizeof(DATA)) < 0)
                perror("writing on stream socket");
}
   Figure 9a  Initiating a UNIX domain stream connection


/*
 * Copyright (c) 1986 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1986 The Regents of the University of California. All rights reserved.0;
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@(#)ustreamread.c       6.4 (Berkeley) 3/7/89";
#endif /* not lint */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>

#define NAME "socket"

/*
 * This program creates a socket in the UNIX domain and binds a name to it.
 * After printing the socket's name it begins a loop. Each time through the
 * loop it accepts a connection and prints out messages from it.  When the
 * connection breaks, or a termination message comes through, the program










PS1:7-32                             Introductory 4.3BSD IPC


 * accepts a new connection.
 */
main()
{
        int sock, msgsock, rval;
        struct sockaddr_un server;
        char buf[1024];

        /* Create socket */
        sock = socket(AF_UNIX, SOCK_STREAM, 0);
        if (sock < 0) {
                perror("opening stream socket");
                exit(1);
        }
        /* Name socket using file system name */
        server.sun_family = AF_UNIX;
        strcpy(server.sun_path, NAME);
        if (bind(sock, &server, sizeof(struct sockaddr_un))) {
                perror("binding stream socket");
                exit(1);
        }
        printf("Socket has name %s\n", server.sun_path);
        /* Start accepting connections */
        listen(sock, 5);
        for (;;) {
                msgsock = accept(sock, 0, 0);
                if (msgsock == -1)
                        perror("accept");
                else do {
                        bzero(buf, sizeof(buf));
                        if ((rval = read(msgsock, buf, 1024)) < 0)
                                perror("reading stream message");
                        else if (rval == 0)
                                printf("Ending connection\n");
                        else
                                printf("-->%s\n", buf);
                } while (rval > 0);
                close(msgsock);
        }
        /*
         * The following statements are not executed, because they follow an
         * infinite loop.  However, most ordinary programs will not run
         * forever.  In the UNIX domain it is necessary to tell the file
         * system that one is through using NAME.  In most programs one uses
         * the call unlink() as below. Since the user will have to kill this
         * program, it will be necessary to remove the name by a command from
         * the shell.
         */
        close(sock);
        unlink(NAME);
}
    Figure 9b  Accepting a UNIX domain stream connection
9

9







Introductory 4.3BSD IPC                             PS1:7-33


_w_r_i_t_e_v(), for read and write _v_e_c_t_o_r.

     It is sometimes necessary to send  high  priority  data
over  a connection that may have unread low priority data at
the other end.  For example, a user interface process may be
interpreting commands and sending them on to another process
through a stream connection.  The user  interface  may  have
filled  the stream with as yet unprocessed requests when the
user types a command to  cancel  all  outstanding  requests.
Rather than have the high priority data wait to be processed
after the low priority data, it is possible to  send  it  as
_o_u_t-_o_f-_b_a_n_d  (OOB)  data.   The  notification of pending OOB
data results in the generation of a SIGURG signal,  if  this
signal  has  been enabled (see the manual page for _s_i_g_n_a_l or
_s_i_g_v_e_c).  See [Leffler 1986] for a more complete description
of  the OOB mechanism.  There are a pair of calls similar to
_r_e_a_d and _w_r_i_t_e that allow  options,  including  sending  and
receiving  OOB  information;  these  are  _s_e_n_d() and _r_e_c_v().
These  calls  are  used  only  with  sockets;  specifying  a
descriptor  for a file will result in the return of an error
status.  These calls also allow _p_e_e_k_i_n_g at data in a stream.
That  is, they allow a process to read data without removing
the data from the stream.  One use of this  facility  is  to
read  ahead  in  a  stream to determine the size of the next
item to be read.  When not using these options, these  calls
have the same functions as _r_e_a_d() and _w_r_i_t_e().

     To send datagrams, one must be allowed to  specify  the
destination.   The call _s_e_n_d_t_o() takes a destination address
as an argument and is therefore used for sending  datagrams.
The  call  _r_e_c_v_f_r_o_m() is often used to read datagrams, since
this call returns the address of the sender, if it is avail-
able,  along  with  the data.  If the identity of the sender
does not matter, one may use _r_e_a_d() or _r_e_c_v().

     Finally, there are a pair of calls that allow the send-
ing  and  receiving  of messages from multiple buffers, when
the address of the recipient must be specified.   These  are
_s_e_n_d_m_s_g()  and  _r_e_c_v_m_s_g().   These  calls are actually quite
general and have other uses, including, in the UNIX  domain,
the  transmission  of  a file descriptor from one process to
another.

     The various options for reading and writing  are  shown
in  Figure  10, together with their parameters.  The parame-
ters for each system call reflect the differences  in  func-
tion  of the different calls.  In the examples given in this
paper, the calls _r_e_a_d() and _w_r_i_t_e() have been used  whenever
possible.



9

9







PS1:7-34                             Introductory 4.3BSD IPC



        /*
         * The variable descriptor may be the descriptor of either a file
         * or of a socket.
         */
        cc = read(descriptor, buf, nbytes)
        int cc, descriptor; char *buf; int nbytes;

        /*
         * An iovec can include several source buffers.
         */
        cc = readv(descriptor, iov, iovcnt)
        int cc, descriptor; struct iovec *iov; int iovcnt;

        cc = write(descriptor, buf, nbytes)
        int cc, descriptor; char *buf; int nbytes;

        cc = writev(descriptor, iovec, ioveclen)
        int cc, descriptor; struct iovec *iovec; int ioveclen;

        /*
         * The variable ``sock'' must be the descriptor of a socket.
         * Flags may include MSG_OOB and MSG_PEEK.
         */
        cc = send(sock, msg, len, flags)
        int cc, sock; char *msg; int len, flags;

        cc = sendto(sock, msg, len, flags, to, tolen)
        int cc, sock; char *msg; int len, flags;
        struct sockaddr *to; int tolen;

        cc = sendmsg(sock, msg, flags)
        int cc, sock; struct msghdr msg[]; int flags;

        cc = recv(sock, buf, len, flags)
        int cc, sock; char *buf; int len, flags;

        cc = recvfrom(sock, buf, len, flags, from, fromlen)
        int cc, sock; char *buf; int len, flags;
        struct sockaddr *from; int *fromlen;

        cc = recvmsg(sock, msg, flags)
        int cc, socket; struct msghdr msg[]; int flags;

      Figure 10  Varieties of read and write commands

_1_0.  _C_h_o_i_c_e_s

     This paper has presented examples of some of the  forms
of  communication  supported by Berkeley UNIX 4.3BSD.  These
have been presented in an order chosen for ease of presenta-
tion.   It is useful to review these options emphasizing the
factors that make each attractive.










Introductory 4.3BSD IPC                             PS1:7-35


     Pipes have the advantage of portability, in  that  they
are supported in all UNIX systems.  They also are relatively
simple to use.  Socketpairs share this simplicity  and  have
the  additional advantage of allowing bidirectional communi-
cation.  The major shortcoming of these mechanisms  is  that
they  require communicating processes to be descendants of a
common process.  They do not allow  intermachine  communica-
tion.

     The two communication domains, UNIX and Internet, allow
processes  with  no  common ancestor to communicate.  Of the
two, only the Internet domain allows  communication  between
machines.  This makes the Internet domain a necessary choice
for processes running on separate machines.

     The choice between datagrams and  stream  communication
is  best made by carefully considering the semantic and per-
formance requirements of the application.   Streams  can  be
both  advantageous and disadvantageous.  One disadvantage is
that a process is only allowed  a  limited  number  of  open
streams,  as  there are usually only 64 entries available in
the open descriptor table.  This can  cause  problems  if  a
single  server  must  talk  with  a large number of clients.
Another is that for delivering a short  message  the  stream
setup  and teardown time can be unnecessarily long.  Weighed
against this are the reliability  built  into  the  streams.
This will often be the deciding factor in favor of streams.

_1_1.  _W_h_a_t _t_o _d_o _N_e_x_t

     Many of the examples presented here can serve as models
for  multiprocess  programs  and  for  programs  distributed
across several machines. In developing  a  new  multiprocess
program,  it  is  often  easiest  to first write the code to
create the processes and communication  paths.   After  this
code  is  debugged, the code specific to the application can
be added.

     An introduction to  the  UNIX  system  and  programming
using  UNIX system calls can be found in [Kernighan and Pike
1984].  Further documentation of the  Berkeley  UNIX  4.3BSD
IPC  mechanisms can be found in [Leffler et al. 1986].  More
detailed information about particular calls and protocols is
provided  in  sections  2,  3 and 4 of the UNIX Programmer's
Manual [CSRG 1986].   In  particular  the  following  manual
pages are relevant:






9

9







PS1:7-36                             Introductory 4.3BSD IPC



    l l.  creating and naming sockets     socket(2), bind(2)
    establishing   connections        listen(2),  accept(2),
    connect(2)  transferring  data       read(2),  write(2),
    send(2),         recv(2)        addresses       inet(4F)
    protocols       tcp(4P), udp(4P).




    _A_c_k_n_o_w_l_e_d_g_e_m_e_n_t_s

     I would like to thank Sam Leffler and  Mike  Karels
for  their  help in understanding the IPC mechanisms and
all the people whose comments have helped in writing and
improving this report.

     This work was sponsored  by  the  Defense  Advanced
Research  Projects  Agency  (DoD),  ARPA Order No. 4031,
monitored by the Naval Electronics Systems Command under
contract  No.  N00039-C-0235.  The views and conclusions
contained in this document are those of the  author  and
should not be interpreted as representing official poli-
cies,  either  expressed  or  implied,  of  the  Defense
Research Projects Agency or of the US Government.



    _R_e_f_e_r_e_n_c_e_s

    B.W. Kernighan & R. Pike, 1984,
    _T_h_e _U_N_I_X _P_r_o_g_r_a_m_m_i_n_g _E_n_v_i_r_o_n_m_e_n_t.
    Englewood Cliffs, N.J.: Prentice-Hall.

    B.W. Kernighan & D.M. Ritchie, 1978,
    _T_h_e _C _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e,
    Englewood Cliffs, N.J.: Prentice-Hall.

    S.J. Leffler, R.S. Fabry, W.N. Joy, P. Lapsley, S. Miller & C. Torek, 1986,
    _A_n _A_d_v_a_n_c_e_d _4._3_B_S_D _I_n_t_e_r_p_r_o_c_e_s_s _C_o_m_m_u_n_i_c_a_t_i_o_n _T_u_t_o_r_i_a_l.
    Computer Systems Research Group,
    Department of Electrical Engineering and Computer Science,
    University of California, Berkeley.

    Computer Systems Research Group, 1986,
    _U_N_I_X _P_r_o_g_r_a_m_m_e_r'_s _M_a_n_u_a_l, _4._3 _B_e_r_k_e_l_e_y _S_o_f_t_w_a_r_e _D_i_s_t_r_i_b_u_t_i_o_n.
    Computer Systems Research Group,
    Department of Electrical Engineering and Computer Science,
    University of California, Berkeley.



9

9



SHAR_EOF
chmod 644 'tutor.txt'
exit 0
#	End of shell archive
