Path: csiph.com!x330-a1.tempe.blueboxinc.net!newsfeed.hal-mli.net!feeder3.hal-mli.net!newsfeed.hal-mli.net!feeder1.hal-mli.net!news.glorb.com!news-out.octanews.net!indigo.octanews.net!news-2.mpls.iphouse.net.POSTED!not-for-mail From: David Dyer-Bennet Newsgroups: comp.os.linux.development.apps Subject: Re: EOF, close(), shutdown(), on POSIX sockets References: <1br4zdh37t.fsf@pfeifferfamily.net> Date: Fri, 06 Jan 2012 10:00:58 -0600 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (usg-unix-v) Cancel-Lock: sha1:osdQaspI1zN/fDlhl9dUX5boooQ= MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Lines: 81 Organization: ipHouse - Welcome Home! NNTP-Posting-Date: 06 Jan 2012 10:00:58 CST NNTP-Posting-Host: 33c4f346.newsreader.iphouse.net X-Trace: DXC=R5d]i44m_c]Ybe[L>83PgZ@;>V08<2]WX@ab@3=d:PmbdiTPUBI>^>03M14C\`8^ X-Complaints-To: abuse@iphouse.net Xref: x330-a1.tempe.blueboxinc.net comp.os.linux.development.apps:359 Joe Pfeiffer writes: > David Dyer-Bennet writes: > >> I'm getting myself confused in an application I'm having trouble getting >> working. I've now got too many different sets of test code that behave >> differently, and which don't always do what I expect. >> >> I'm developing this on a Centos 5 system. The actual code is in Perl, >> but I don't think that's important (based on strace monitoring of the >> actual system calls being made, and what happens). Portability isn't a >> requirement (but is my default way of thinking in general). >> >> I'm working on the core of a tcp proxy application. The overall >> architecture is that the proxy server listens on a socket, accepts >> connections, reads the first line and decides (based on information >> transmitted in the local protocol that the request is encoded in) what >> server to send that request to, forks a child, the child connects to the >> chosen server, and drops the client and server socket into the core >> relay bit (while the parent goes back to accept the next connection). >> >> The proxy is supposed to be transparent (except, obviously, that the >> real server can tell where the connection it gets came from if it asks). >> >> Much of it seems to work :-). >> >> One thing I think I'm having trouble with (tests using netcat don't do >> quite what I expect) involves what to do in the proxy copy loop when I >> get EOF (meaning a 0 return from a read, no error). The proxy is >> copying bi-directionally between two sockets, call them socket A and >> socket B. >> >> If I receive EOF when I read from A, I think I should do shutdown(B, >> SHUT_WR), and if I receive EOF when I read from B, I should similarly do >> shutdown (A, SHUT_WR). (And there is accounting about which sockets >> I've received EOF reading from, to avoid trying to read them in future, >> and to keep track of when both sides have shut down so I should close >> everything and exit.) This appears to be necessary to propogate the EOF >> through the proxy from client to server or vice-versa. Right? >> >> One confusing factor: in the strace from nc (netcat), I get: >> >> 17:58:48.764342 poll([{fd=3, events=POLLIN}, {fd=0, >> events=POLLIN}], 2, -1) = 2 ([{fd=3, revents=POLLIN}, {fd=0, >> revents=POLLIN}]) >> 17:58:48.764474 read(3, "", 1024) = 0 >> >> nc receives EOF from the proxy (port 3 is the socket connected to the >> proxy). >> >> 17:58:48.764575 shutdown(3, 0 /* receive */) = 0 >> >> nc promptly shuts down the socket it just received EOF on. Should I be >> doing this in addition to the other? >> >> Another confusing factor: immediately after this, nc reads 1024 bytes >> from stdin (leaving it in the middle of the test file, about 56%; and >> that's only 1/8 of the amount of data requested), writes it to 3, then >> closes and exits -- meaning it aborts reading and transmitting the input >> file. >> >> The nc that the strace was from is invoked as: >> nc localhost $PORT1 < $TD1 >$TDIR/o2 & >> where $PORT1 is 8000 and is where the proxy is listening. > > I've never been able to get a clear understanding of exactly the > conditions under which a receiver will get an EOF so it can know the > other end has shut down. For my own applications (and protocols) I've > taken to sending a distinguished character (a period '.' in many cases, > appropriately enough) as the last output from a transmitter, so I can > treat it as if it were an EOF and shut down the receiver appropriately. I know the feeling. And in fact bits of the actual protocol I'm proxying do have some things like that -- but unfortunately not all of them. And I'm half-thinking of the basic copying-both-ways engine as being general-purpose rather than specific to this one protocol. -- David Dyer-Bennet, dd-b@dd-b.net; http://dd-b.net/ Snapshots: http://dd-b.net/dd-b/SnapshotAlbum/data/ Photos: http://dd-b.net/photography/gallery/ Dragaera: http://dragaera.info