Can you partially shutdown() a UNIX domain socket?
Andrew Vignaux
Andrew.Vignaux at comp.vuw.ac.nz
Tue Apr 2 20:13:30 AEST 1991
Can I shutdown(,1) an AF_UNIX socket so that it propagates the
"end-of-file" indication to the other end? I seem to be able to do this
with AF_INET sockets. Am I asking too much from shutdown()?
I have tried the following program under MORE/bsd on our hp300s, HPUX
7.0 on 9000/{8,3}00, SunOS 4.1, and AIX 3.1. The program compiled with
-DINET gets a 0 read in the child after shutdown() is called in the
parent, the -UINET program doesn't. BTW: my original 4-fd select() loop
in the parent has been simplified (too much?) into a synchronised
for(;;) loop.
Should I just use pipe()s? My real program talks to a remote server
using INET sockets but occasionally I want to fire up a local program
and talk to that. If I can get the shutdown() to work I can use the
same processing loop because everyone's a socket. Actually, my real
program is in perl and I've already rewritten it using pipes ;-)
Andrew
--
Domain address: Andrew.Vignaux at comp.vuw.ac.nz
-------------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#ifndef INET
# include <sys/un.h>
# define NAME "socket"
#else
# include <netinet/in.h>
#endif
#define DATA1 "In Xanadu, did Kublai Khan . . ."
#define DATA2 "A stately pleasure dome decree . . ."
#define DATA3 "And now for something completely different . . ."
int main()
{
int family;
int s, child;
int sockets[2];
char buf[1024];
#ifndef INET
struct sockaddr_un addr;
#else
int l;
struct sockaddr_in addr;
#endif
#ifndef INET
addr.sun_family = family = AF_UNIX;
strcpy (addr.sun_path, NAME);
#else
addr.sin_family = family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
#endif
if ((s = socket(family, SOCK_STREAM, 0)) < 0) {
perror("master: socket");
exit(1);
}
if (bind(s, &addr, sizeof(addr)) < 0) {
perror("master: bind");
exit(1);
}
#ifdef INET
l = sizeof(addr);
if (getsockname(s, &addr, &l)) {
perror("master: getsockname");
exit(1);
}
#endif
listen (s, 5);
setbuf (stdout, (char *)NULL);
if ((child = fork()) == -1)
perror("fork");
else if (child == 0) { /* This is the child. */
int r;
if ((sockets[1] = accept(s, (struct sockaddr *)0, (int *)0)) < 0) {
perror("child: accept");
exit(1);
}
#ifndef INET
if (unlink (addr.sun_path) < 0)
perror ("child: unlink");
#endif
while (1) {
r = read(sockets[1], buf, 1024);
if (r < 0) {
perror("child: read");
exit (1);
}
else if (r == 0) {
(void) fprintf (stderr, "<eof>\n");
break;
}
(void) printf("%d==>%.*s\n", r, r, buf);
if (write(sockets[1], DATA2, sizeof(DATA2)) < 0)
perror("child: write");
}
if (write(sockets[1], DATA3, sizeof(DATA3)) < 0)
perror("child: end write");
if (close(sockets[1]) < 0)
perror("child: close");
} else { /* This is the parent. */
int i, r;
if ((sockets[0] = socket(family, SOCK_STREAM, 0)) < 0) {
perror("parent: socket"); exit(1);
}
if (connect (sockets[0], &addr, sizeof(addr)) < 0) {
perror("parent: connect"); exit(1);
}
for (i = 0; i < 5; i++) {
if (write(sockets[0], DATA1, sizeof(DATA1)) < 0)
perror("parent: write");
if ((r = read(sockets[0], buf, 1024)) < 0)
perror("parent: read");
(void) printf("%d-->%.*s\n", r, r, buf);
}
if (shutdown(sockets[0], 1) < 0)
perror("parent: shutdown");
if ((r = read(sockets[0], buf, 1024)) < 0)
perror("parent: end read");
(void) printf("%d**>%.*s\n", r, r, buf);
if (close(sockets[0]) < 0)
perror("parent: close");
}
return 0;
}
More information about the Comp.unix.programmer
mailing list