Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: server-side Socket does not recognize broken connection. Date: Wed, 29 May 2019 08:30:18 -0400 Organization: A noiseless patient Spider Lines: 52 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Injection-Date: Wed, 29 May 2019 12:30:21 -0000 (UTC) Injection-Info: reader02.eternal-september.org; posting-host="334fef55bea5a4abe4c9660ba97c770d"; logging-data="529"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+/th1jSOB7bwitmFXjsOY7" User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.7.0 Cancel-Lock: sha1:gWl2xALGwav67Da+ygF96Y5icz4= In-Reply-To: Content-Language: en-US Xref: csiph.com comp.lang.java.programmer:38969 On 5/29/2019 7:03 AM, Andreas Leitgeb wrote: > I have a ServerSocket on some port. whenever ".accept()" returns a > connection, it goes to a loop that (among doing other stuff) polls > the socket's input stream's ".available()" and if it returns > 0 > it reads and processes that data. (SSCCE at end of post) > > A client (e.g. using plain old "telnet" on unix) connects, types a > bit, then breaks the connection using Ctrl-] and "close", and is back > on the shell. (closing the terminal window that's running telnet > has same effect, ditto killing the telnet process - apparently > whatever breaks, or even properly shuts down the connection from > client side.) > > The Socket on server side, however keeps reporting 0 on .available(), > rather than throwing some exception for the broken socket. > > Single stepping the .available() method (class AbstractPlainSocketImpl) > shows that it just never receives the ConnectionResetException, and thus > won't ever get to throw new IOException("Stream closed.") itself. > Field resetState never changes away from CONNECTION_NOT_RESET. > > What am I doing wrong wrt. EOF-detection in ".available()" ? Using available(), I think. :) available() reports (or estimates) the number of bytes that can be read without blocking, that is, the number of bytes already received and buffered. "My buffer is empty right now" is not the same thing as "There will never be any more input," so available()==0 is not a test for EOF. It is true that once you've read all the bytes that will ever appear you will find available()==0, but the implication is one-directional. To discover that the socket has been closed, I think you must actually attempt to read something. The documentation for available() doesn't say so explicitly -- but then, there are so many different implementations of InputStream that documenting the exact behavior of all of them would be daunting or perhaps even impossible. > PS: The real code does more interesting stuff while no input is available, > so it cannot wait blockingly. The real code also has other exits from the > loop (based on input received), but that's not relevant for this SSCCE. One approach (there might be others) would be to create a thread that just calls read() until it gets an exception, depositing the input in a Queue (or similar) that the main line can poll() without blocking. At EOF or other exception, the reading thread would enqueue a "poison pill" to alert the main line that something's amiss. -- esosman@comcast-dot-net.invalid Six hundred two days to go.