[net.wanted.sources] Need reliable datagrams

jpn@teddy.UUCP (John P. Nelson) (09/16/86)

I have an application that needs to reliably send packets of data
around among several tasks in a system.

I have tried using bidirectional SOCK_STREAM type sockets, but that
serializes my data (it removes the packet boundaries) and, besides, I
run out of descriptors because each socket must be CONNECTed to another
socket on the other end (and each task needs two channels, one for
normal data, and one for breakthru data).

I have also tried using SOCK_DGRAM sockets:  The interface is fine,
but under high load conditions, I lose as many as 20% of my packets!!

My SUN manual lists a SOCK_SEQPACKET protocol as being "planned but
not implemented"; this looks like just what I need.  Too bad.

Has anyone solved this problem?  If I can't get a good UNIX solution,
I'll have to implement my own reliable delivery protocol at task level
(I'm not much of a kernel hacker) - and I'd really HATE to have to do that!
We have all kinds of source licences here:  BSD4.2, BSD4.3, ULTRIX 1.2,
and SUN 3.0.  Any kind of pointers would be appreciated.

  John P. Nelson
  GenRad  M.S. 6
  Concord, MA 01742

       decvax!genrad!teddy!jpn
seismo!talcott!panda!teddy!jpn

chris@umcp-cs.UUCP (Chris Torek) (10/07/86)

In article <3189@teddy.UUCP> jpn@teddy.UUCP (John P. Nelson) writes:
>I have an application that needs to reliably send packets of data
>around among several tasks in a system.
...
>My SUN manual lists a SOCK_SEQPACKET protocol as being "planned but
>not implemented"; this looks like just what I need.  Too bad.

>We have all kinds of source licences here:  BSD4.2, BSD4.3, ULTRIX 1.2,
>and SUN 3.0.  Any kind of pointers would be appreciated.

While this works only under 4.3 systems, you can use AF_XNS sockets
to send packets.  SPP sockets are indeed SEQPACKET sockets.

	int s = socket(AF_XNS, SOCK_SEQPACKET, 0);

	if (s < 0)
		gripe();

You had best read the new IPC primer first.

Alternatively, you can drop your own `packet' protocol on top
of TCP:

/*
 * Write a message packet.
 */
void
wrmsg(fd, buf, size)
	int fd;
	char *buf;
	int size;
{
	long nsize = htonl(size);

	/*
	 * Could use writev here, for efficiency...
	 */
	if (write(fd, (char *) &nsize, sizeof (nsize)) != sizeof (nsize) ||
	    write(fd, buf, size) != size)
		gripe();
}

/*
 * `reliable' read
 */
void
rread(fd, buf, n)
	int fd;
	char *buf;
	int n;
{
	int r;

	while (n > 0) {
		r = read(fd, buf, n);
		if (r <= 0)
			gripe();
		buf += r;
		n -= r;
	}
}

int
rdmsg(fd, buf, size)
	int fd;
	char *buf;
	int size;
{
	long nsize, discard;
	char trash[BUFSIZ];

	rread(fd, (char *) &nsize, sizeof (nsize));
	nsize = ntohl(nsize);
	discard = nsize - size;
	if (nsize > size)
		nsize = size;
	size = nsize;
	rread(fd, buf, (int) nsize);
	while (discard > 0) {
		nsize = discard > BUFSIZ ? BUFSIZ : discard;
		nsize = read(fd, trash, (int) nsize);
		if (nsize <= 0)
			gripe();
		discard -= nsize;
	}
	return (size);
}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1516)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu