Andrew.Vignaux@comp.vuw.ac.nz (Andrew Vignaux) (04/02/91)
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@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; }
Andrew.Vignaux@comp.vuw.ac.nz (Andrew Vignaux) (04/07/91)
In <1991Apr02.101330.22133@comp.vuw.ac.nz>, I wrote: > 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()? > [excessively long example program deleted] The 4.3 "Devil" book has a justification for this on page 320, Socket-to-Protocol Interface: : * PRU_SHUTDOWN: Shut down socket data transmission. This call is : used to indicate that no more data will be sent. The protocol : may, at its discretion, deallocate any data structures related to : the shutdown% and/or notify a connected peer of the shutdown. So, it seems that it's up to the protocol handling code. Why is the "may, at its discretion" qualification there though? To handle protocols that you can't partially shutdown()? Are there any (stream) domains where it is hard to notify a peer of the partial shutdown? Is AF_UNIX really such a domain? Without being able to shutdown() one side of a socket is there much useful work you can do with socketpair()@ that you can't do (more portably) with pipe()s#? Actually I can partially answer that myself (again): datagrams and passing access rights. Andrew -- Domain address: Andrew.Vignaux@comp.vuw.ac.nz % Should that be some other word than shutdown, e.g. socket to be shutdown? @ I could find only one program that used socketpair() (in the portion of our source archive that happened to be uncompressed) and it seemed to be in a routine which usually used ptys. # When another domains/types/protocol combination acknowledges the PRU_CONNECT2 request this question shall be considered null and void.