Stevens doesn't say shutdown-based transactions violate good practices, I don't think.

shutdown(1) forces half of the connection to be closed. I often use this for the same purpose as the original poster. The other end has no obligation to close the other half when this happens. Stevens is talking about close(), which is a different beast. It decrements a reference count, and if it reaches zero, shuts down both halves of the connection. shutdown doesn't bother with reference counts; it immediately forces one or both halves shut.

You should never close a connection before reading out all of the data (that'll lock up the port for a very long time and may send a broken pipe signal to the other end.) I assume the same thing would happen if you did shutdown(0) with data in transit. But it's fine to shutdown(1) the half you're writing to; it's then the problem of the other end to read everything out and take that half down.

But in answer to the original question, you're not going to be able to send an intermediate EOF. You'll either have to change the protocol (4-byte network byte-order chunk sizes work fine, with zero meaning end-of-message), or make new connections. There are nasty little wrinkles in TCP that you could try to exploit (eg out of band data), but that'll do you much more harm than good. And it's still a protocol change, just at a different level.

But I don't really understand what was meant by "the third party server closes the socket and therefore I cannot read their response". As long as they write the full response to the socket before calling close(), it'll be fine -- you can read their response, get an EOF, and do a close() yourself. Are you getting a broken pipe? What happens?

Just for illustration, here's a simple shutdown-based handshake (yes, I just wanted to see if I could do it).perl -MIO::Socket -we 'sub S{$l=IO::Socket::INET->new(LocalPort=>9123,Listen=>5);$s=$l->accept();print "rS:$_" while(<$s>); print $s "what?\n";} sub C{sleep 1;$c=IO::Socket::INET->new(PeerAddr=>"localhost:9123"); print $c "hello\n"; shutdown($c,1); print "rC:$_" while(<$c>);} exit(fork?S:C)'

Update: Wow, I was way too argumentative in my initial response. It looked like I was disagreeing with lots of stuff I fully agree with (eg how half-closes are realized in TCP packets). I rewrote the first sentence to be more specific.


In reply to Re: Re: Socket dilemma - sending EOF by sfink
in thread Socket dilemma - sending EOF by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.