Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #38971

Re: server-side Socket does not recognize broken connection.

Newsgroups comp.lang.java.programmer
Date 2019-05-29 07:14 -0700
References <slrnqespnm.cfl.avl@logic.at>
Message-ID <9b92a0e6-3558-4dda-9677-98ad8925e63c@googlegroups.com> (permalink)
Subject Re: server-side Socket does not recognize broken connection.
From Eric Douglas <e.d.programmer@gmail.com>

Show all headers | View raw


On Wednesday, May 29, 2019 at 7:03:29 AM UTC-4, 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()" ?
> 
> 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.
> 
> PS: unlike most of my recent posts, this one is *not* Java11-related.
> 
> 
> SSCCE:  ServerTest.java
> 
> import javax.net.ServerSocketFactory;
> import java.net.ServerSocket;
> import java.net.Socket;
> import java.io.InputStream;
> import java.io.IOException;
> 
> public class ServerTest {
>    public static void main(String[] args) throws IOException,InterruptedException {
> 
>       ServerSocket serverSocket = ServerSocketFactory.getDefault().createServerSocket(65432);
>       Socket clientSocket = serverSocket.accept();
>       InputStream is = clientSocket.getInputStream();
> 
>       while (true) {
>          if (is.available() > 0) {
>             System.out.println( is.read() );
>          }
>          Thread.sleep(100);
>       }
>    }
> }

I haven't stress tested mine, but it seems to work.  I just set up a socket connection for one machine to send text to one or two other machines.
First I create one listener as an instance of java.net.ServerSocket with a specific port, and assign setSoTimeout().  Then I run this try block.
try {
     while (keepServerAlive) {
          try {
               new SocketServer(listener.accept(), clientNumber++).start();
          } catch (final SocketTimeoutException e) {
               // end extra thread - there's always one idle thread waiting for new connections
          }
     }
} finally {
     listener.close();
}
keepServerAlive is a boolean variable I can set elsewhere to shut down the server side.  clientNumber is a simple int for tracking the number of clients connected since the server was started.  This loop should create a new SocketServer whenever accept() succeeds, failure should hit the timeout.

SocketServer is a subclass set up like this.
private static class SocketServer extends Thread {
     private final Socket socket;
     private final int clientNumber;

     public SocketServer(final Socket socket, final int clientNumber) {
          this.socket = socket;
          this.clientNumber = clientNumber;
     }
     @Override
     public void run() {
          PrintWriter out = null;
          try {
               final BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
               out = new PrintWriter(socket.getOutputStream(), true);
// out variable can be referenced elsewhere to send messages to this client
// this thread will also die when flag is set to shut down server
               while (keepServerAlive) {
                    final String input = in.readLine();
// check if client not responding, other value to end session may be sent into this condition
                    if (input == null) {
                         break;
                    }
               }
          } catch (final IOException e) {
// I crash here if client socket terminates
// finally, run cleanup to close the PrintWriter if not null and close the socket

The rest of that class just involves the logic to direct the output of a Blender log.  The client side is a separate class with the mirror logic, creating an instance of Socket with the server name and port, opening it's own InputStreamReader and PrintWriter for 2-way communication, with a background thread running an infinite readLine on the input, checking for null or IOException.  In my case I made a JFrame on the client with a windowClosing listener set to interrupt that background thread, and a JTextArea to display the server messages.

Back to comp.lang.java.programmer | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

server-side Socket does not recognize broken connection. Andreas Leitgeb <avl@logic.at> - 2019-05-29 11:03 +0000
  Re: server-side Socket does not recognize broken connection. Eric Sosman <esosman@comcast-dot-net.invalid> - 2019-05-29 08:30 -0400
  Re: server-side Socket does not recognize broken connection. Joerg Meier <joergmmeier@arcor.de> - 2019-05-29 14:58 +0200
    Re: server-side Socket does not recognize broken connection. Andreas Leitgeb <avl@logic.at> - 2019-05-29 14:50 +0000
      Re: server-side Socket does not recognize broken connection. Eric Douglas <e.d.programmer@gmail.com> - 2019-05-29 08:22 -0700
        Re: server-side Socket does not recognize broken connection. Andreas Leitgeb <avl@logic.at> - 2020-01-30 15:22 +0000
      Re: server-side Socket does not recognize broken connection. Martin Gregorie <martin@mydomain.invalid> - 2019-05-29 16:06 +0000
  Re: server-side Socket does not recognize broken connection. Eric Douglas <e.d.programmer@gmail.com> - 2019-05-29 07:14 -0700
  Re: server-side Socket does not recognize broken connection. trisha guillot <guillottrisha347@gmail.com> - 2019-05-31 20:13 -0700
  Re: server-side Socket does not recognize broken connection. Marcel Mueller <news.5.maazl@spamgourmet.org> - 2019-06-01 16:08 +0200

csiph-web