kc@rna.UUCP (Kaare Christian) (07/23/86)
Following the cookbook in ``4.2BSD IPC Primer'' I have managed to make a machine-macine connection between two programs. All things considered it was easier than I expected, just a mornings work. Anyway I wondered if anyone could tell me more about the bind call. For ipc in the Unix domain it seems that both parties need a bind following socket creation, but when ipc is in the internet domain only the server needs a bind. Why?? Ques 2. When you use the internet domain, but client and server are on the same machine, does your data go though the loop back connection? Is this the reason for the loop back connection. Just thought I'd ask. Kaare Christian cmcl2!rna!kc
chris@umcp-cs.UUCP (Chris Torek) (08/06/86)
In article <523@rna.UUCP> kc@rna.UUCP (Kaare Christian) writes: >For ipc in the Unix domain it seems that both parties need a bind >following socket creation, but when ipc is in the internet domain only >the server needs a bind. Why?? Sounds like a bug to me. It is not true in 4.3BSD beta-plus-upgrades. (See example programs below.) >Ques 2. When you use the internet domain, but client and server are on >the same machine, does your data go though the loop back connection? >Is this the reason for the loop back connection. Actually, that depends on the driver. Some Ethernet boards cannot send to themselves; so drivers for those will call the loopback driver in such cases. Other boards do not have this limitation, but usually the driver will call the loopback code anyway. I threw the following code together to see whether the client needed to bind before connecting. (It did not.) Extract the files (the script makes a fresh directory for them), compile, and run with an argument as to what socket to create. Careful: `se' (the server) removes any file with the same name as that socket. : Run this shell script with "sh" not "csh" PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH export PATH all=FALSE if [ x$1 = x-a ]; then all=TRUE fi echo Making directory test_AF_UNIX mkdir test_AF_UNIX echo Extracting test_AF_UNIX/Makefile sed 's/^X//' <<'//go.sysin dd *' >test_AF_UNIX/Makefile DESTDIR= CFLAGS= -O STD= cl se all: ${STD} ${STD}: error.o ${CC} ${CFLAGS} -o $@ $@.c error.o install: @echo "test programs are never installed, silly!" clean: rm -f *.o *.s a.out core *.bak rm -f ${STD} depend: for i in ${STD} error; do \ ${CC} -M $$i.c | sed -e 's/\.o//' | \ awk '{ if ($$1 != prev) { if (rec != "") print rec; \ rec = $$0; prev = $$1; } \ else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ else rec = rec " " $$2 } } \ END { print rec }'; done >makedep echo '/^# DO NOT DELETE THIS LINE/+2,$$d' >eddep echo '$$r makedep' >>eddep echo 'w' >>eddep cp Makefile Makefile.bak ed - Makefile <eddep rm eddep makedep echo '# DEPENDENCIES MUST END AT END OF FILE' >>Makefile echo '# IF YOU PUT STUFF HERE IT WILL GO AWAY' >>Makefile echo '# see make depend above' >>Makefile # DO NOT DELETE THIS LINE -- make depend uses it cl: cl.c /usr/include/stdio.h /usr/include/sys/types.h cl: /usr/include/sys/socket.h /usr/include/sys/un.h se: se.c /usr/include/stdio.h /usr/include/sys/types.h se: /usr/include/sys/socket.h /usr/include/sys/un.h error: error.c /usr/include/stdio.h # DEPENDENCIES MUST END AT END OF FILE # IF YOU PUT STUFF HERE IT WILL GO AWAY # see make depend above //go.sysin dd * if [ `wc -c < test_AF_UNIX/Makefile` != 1238 ]; then made=FALSE echo error transmitting test_AF_UNIX/Makefile -- echo length should be 1238, not `wc -c < test_AF_UNIX/Makefile` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 test_AF_UNIX/Makefile echo -n ' '; ls -ld test_AF_UNIX/Makefile fi echo Extracting test_AF_UNIX/cl.c sed 's/^X//' <<'//go.sysin dd *' >test_AF_UNIX/cl.c X/* * client */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #define suntosa(x) ((struct sockaddr *) (x)) #define namesize(x) (strlen((x)->sun_path) + sizeof ((x)->sun_family)) struct sockaddr_un servname; int servsock; extern int errno; char *strcpy(); main(argc, argv) int argc; char **argv; { char buf[20]; if (argc < 2) error(1, 0, "usage: cl <server>"); if ((servsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) error(1, errno, "socket"); servname.sun_family = AF_UNIX; (void) strcpy(servname.sun_path, argv[1]); if (connect(servsock, suntosa(&servname), namesize(&servname))) error(1, errno, "connect"); if (write(servsock, "hi", 2) != 2) error(1, errno, "write"); if (read(servsock, buf, 5) != 5) error(1, errno, "read"); buf[5] = 0; printf("\"hi\" => \"%s\"\n", buf); exit(0); } //go.sysin dd * if [ `wc -c < test_AF_UNIX/cl.c` != 855 ]; then made=FALSE echo error transmitting test_AF_UNIX/cl.c -- echo length should be 855, not `wc -c < test_AF_UNIX/cl.c` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 test_AF_UNIX/cl.c echo -n ' '; ls -ld test_AF_UNIX/cl.c fi echo Extracting test_AF_UNIX/error.c sed 's/^X//' <<'//go.sysin dd *' >test_AF_UNIX/error.c X/* * For other systems... mine comes from my C library. */ #ifdef lint X/*VARARGS3 ARGSUSED*/ error(quit, e, fmt) int quit, e; char *fmt; {;} #else #include <stdio.h> char *_argv0; /* set by C start up code before calling main */ error(quit, e, fmt, args) int quit; register int e; char *fmt; { extern char *sys_errlist[]; extern int sys_nerr; if (_argv0) (void) fprintf(stderr, "%s: ", _argv0); _doprnt(fmt, &args, stderr); if (e) { if (e < sys_nerr) (void) fprintf(stderr, ": %s", sys_errlist[e]); else (void) fprintf(stderr, ": unknown error code %d", e); } (void) putc('\n', stderr); (void) fflush(stderr); if (quit) exit(quit); } #endif //go.sysin dd * if [ `wc -c < test_AF_UNIX/error.c` != 677 ]; then made=FALSE echo error transmitting test_AF_UNIX/error.c -- echo length should be 677, not `wc -c < test_AF_UNIX/error.c` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 test_AF_UNIX/error.c echo -n ' '; ls -ld test_AF_UNIX/error.c fi echo Extracting test_AF_UNIX/se.c sed 's/^X//' <<'//go.sysin dd *' >test_AF_UNIX/se.c X/* * server */ #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/un.h> #define suntosa(x) ((struct sockaddr *) (x)) #define namesize(x) (strlen((x)->sun_path) + sizeof ((x)->sun_family)) struct sockaddr_un servname, cliname; int servsock, clisock; extern int errno; char *strcpy(); main(argc, argv) int argc; char **argv; { char buf[20]; int fromlen; if (argc < 2) error(1, 0, "usage: se <server>"); if ((servsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) error(1, errno, "socket"); (void) unlink(argv[1]); /* clear the way */ servname.sun_family = AF_UNIX; (void) strcpy(servname.sun_path, argv[1]); if (bind(servsock, suntosa(&servname), namesize(&servname))) error(1, errno, "connect"); if (listen(servsock, 1)) error(1, errno, "listen"); fromlen = sizeof (cliname); if ((clisock = accept(servsock, suntosa(&cliname), &fromlen)) < 0) error(1, errno, "accept"); if (read(clisock, buf, 2) != 2) error(1, errno, "read"); if (write(clisock, "there", 5) != 5) error(1, errno, "write"); exit(0); } //go.sysin dd * if [ `wc -c < test_AF_UNIX/se.c` != 1063 ]; then made=FALSE echo error transmitting test_AF_UNIX/se.c -- echo length should be 1063, not `wc -c < test_AF_UNIX/se.c` else made=TRUE fi if [ $made = TRUE ]; then chmod 644 test_AF_UNIX/se.c echo -n ' '; ls -ld test_AF_UNIX/se.c fi made=TRUE if [ $made = TRUE ]; then chmod 755 test_AF_UNIX echo -n ' '; ls -ld test_AF_UNIX fi -- 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