Return to BSD News archive
Xref: sserve comp.unix.programmer:15430 comp.unix.bsd:13512 Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.uwa.edu.au!DIALix!not-for-mail From: peter@melbourne.DIALix.oz.au (Peter Wemm) Newsgroups: comp.unix.programmer,comp.unix.bsd Subject: Re: Detecting dead client in BSD socket Date: 7 Mar 1994 16:43:49 +0800 Organization: DIALix Services, Melbourne, Australia. Lines: 147 Sender: peter@melbourne.DIALix.oz.au Message-ID: <2lepg5$fi4$1@melbourne.DIALix.oz.au> References: <1994Mar3.154852.24090@il.us.swissbank.com> <2l92ia$hrd@u.cc.utah.edu> <1994Mar5.142417.28947@noao.edu> NNTP-Posting-Host: melbourne.dialix.oz.au Keywords: socket bsd death X-Newsreader: NN version 6.5.0 #55 (NOV) rstevens@noao.edu (W. Richard Stevens) writes: >> > Is there a way to determine, from the server side, whether a client has >> > closed its end of the connection in a BSD socket? >> >> Set SO_KEEPALIVE as an option and notification will be more immediate; be >> sure and use select on the socket and check for exceptional conditions. >Check for "readability" not an "exception" condition. If the other end >dies, or dies and reboots, your socket will become readable after the >keepalive probe(s) are sent; issue a read, and the error will probably >be ETIMEDOUT or ECONNRESET. Check Chapter 23 of my recent book "TCP/IP >Illustrated" for lots of information on keepalives. (This chapter is >also reprinted in the Feb. 94 issue of Interop's ConneXions.) If you're >going to use keepalives, you need to understand how they're implemented >by TCP, regardless whether you use sockets or TLI. > >> On the other hand, if it's a socket library on top of TLI and your UNIX >> obeys the notification protocol, >Socket libraries on systems such as SVR4 are *not* built on top of TLI. >This is a fundamental misconception that is continually repeated. Sockets >are built on top of TPI, the "Transport Provider Interface", a spec you >can ftp from ftp.ui.org in pub/osi/tpi.ps. The socket library talks to >TPI just like TLI does. Both require a special kernel streams module >to help: sockmod and timod. (Rago correctly talks about this in Section >12.3 of his book "UNIX System V Network Programming".) TLI may be "closer" >to TPI than sockets (since they're both made to look OSI-ish) but to say >that sockets in SVR4 are built on top is TLI is plain wrong. >> rewriting directly to TLI will let you >> not only run on other protocol stacks (XNS, IPX, OSI, etc.), it will >> provide disconnect notification. >Ah, but protocol independence does have its price, doesn't it :-) Using >sockets I can get or set the SO_KEEPALIVE option with 3 lines of code >(assignment, function call, error handling). Please show the equivalent >TLI code. I am especially interested in your implementation of getsockopt() >using TLI (not XTI). > Rich Stevens (rstevens@noao.edu) SVR4 has two socket implementations.. There's the Lachman derived protocol stack with the Sun/AT&T/whoever 'sockmod' and the user library, and then there's the Wollongong (sp?) Win/TCP that's used on the AT&T / NCR machines. The sockmod approach, as you say, is built over TPI. It is a _reasonably_ faithful implementation of the traditional socket semantics, but there are still some "gotchas" there to keep the programmer on their toes. There are a couple of real dangers with the user-level library that keeps a malloc()ed "state" per open socket descriptor. Try dup()in them and other things like that and watch your memory leak away. :-( However, Win/TCP as I understand it, is built over the top of TLI. It has the classic TLI problems there, like accept() blowing up if there are more than one queued connection and so on. The 'StarServer' family (I'm on one of the starserver mailing lists, but I've never used one..) have problems with this every so often. Here's some food for thought. This code was once extracted from the X11 source. I believe it's basically a cleaned up SVR4 version of some existing X code. Oh, and this is setsockopt, not getsockopt as you requested.. :-) --------------------------- #include <stdio.h> #include <sys/types.h> #include <sys/sockio.h> #include <sys/tiuser.h> #include <sys/stropts.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/if.h> #include <sys/ioctl.h> /* * Streams-TLI emulation of setsockopt(2) */ static void Terror(); setsockopt(fd,level,opt,way,waysize) int fd; int *way; { struct optdesc { int level; /* Protocol Level Affected */ int optname; /* option name to modify */ int len; /* sizeof value */ int value; /* value set or retrieved */ }; struct t_optmgmt req, ret; struct optdesc optreq, optret; extern int t_errno; memset((char *)&req, 0, sizeof(req)); req.opt.buf = (char *)&optreq; req.opt.len = sizeof(optreq); req.opt.maxlen = sizeof(optreq); req.flags = T_NEGOTIATE; memset((char *)&ret, 0, sizeof(ret)); ret.opt.buf = (char *)&optret; ret.opt.len = sizeof(optret); ret.opt.maxlen = sizeof(optret); ret.flags = 0; memset((char *)&optret, 0, sizeof(optret)); memset((char *)&optreq, 0, sizeof(optreq)); optreq.optname = opt; optreq.level = level; optreq.value = *way; optreq.len = waysize; if(t_optmgmt(fd, &req, &ret) < 0) { Terror("t_optmgmt"); return(-1); } if(ret.flags != T_SUCCESS && ret.flags != T_NEGOTIATE) { fprintf(stderr, "t_optmgmt %d: ret.flags=0x%x\n", opt, ret.flags); return(-1); } return(0); } static void Terror(s) char *s; { extern int t_errno; if(t_errno == TSYSERR) perror(s); else t_error(s); } --------------------------- Lovely, isn't it... :-) -Peter -- Peter Wemm <peter@DIALix.oz.au> - NIC Handle: PW65 - The keeper of "NN" "My computer is better than your computer" - Anonymous (Overheard, shortly after the creation of the second computer....)