简体   繁体   中英

Peek on a socket InputStream

I would like to test the connection between a client and a server in a ScheduledExecutorService every x ms while processing received data from the distant host.

So I did something like this:

public class MyClass {
    private final ScheduledExecutorService _timer = Executors.newScheduledThreadPool(1);
    private Socket _connection;

    public void connectToDistantHost() {
        try {
            _connection = new Socket();
            _connection.connect(_adresseServeur);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        //let another object know the connection is ok
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } catch (IOException e) {
            e.printStackTrace();
        }

        _timer.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                testConnection();
            }
        }, 0, 200, TimeUnit.MILLISECONDS);
    }

    private void testConnection() {
        //would like to peek on the socket's inputstream to know if something's wrong
    }

    private void myProcessing() {
        while (true) {
            ...

            //read what's inside stream
            //process it in a thread
        }
    }
} 

So, if I .read() on the Socket's inputstream it'll screw myProcessing(). I thought about wraping the inputstream in a BufferedReader and mark the buffer position before I read and then reset the position, but as the testing and the processing are in two differents thread it won't work anyway.

How can I do that? Knowing that I did it in c# without much problem:

class TraitementEnvoiClient {
    ...
    private void testConnection(Object obj, ElapsedEventArgs args) {
        _connectionIsOk = _connexionAuServeur.IsConnected();

        if (!_connectionIsOk) {
            tryToReconnect();
        }
    }
}

public static class ExtensionTcpClient {
    //Credit to ElFenix: http://social.msdn.microsoft.com/Forums/en-US/c857cad5-2eb6-4b6c-b0b5-7f4ce320c5cd/c-how-to-determine-if-a-tcpclient-has-been-disconnected?forum=netfxnetcom
    public static bool IsConnected(this TcpClient client) {
        // Detect if client disconnected
        try {
            if (client.Client.Poll(0, SelectMode.SelectRead)) {
                byte[] buff = new byte[1];
                if (client.Client.Receive(buff, SocketFlags.Peek) == 0) {
                    // Client disconnected
                    return false;
                }
            }
        } catch (SocketException se) {
            return false;
        }
        return true;
    }
}

Thank you

Edit: I would like to make something like that:

private static boolean isConnected(Socket client) {
    try {
        InputStream is = client.getInputStream();
        if(is.peek() == -1) return false;
        OutputStream os = client.getOutputStream();
        os.write(new byte[]{}); //if it fails a IOException will trigger
    } catch(SocketException se) {
        return false;
    } catch(IOException ioe) {
        return false;
    }
    return true;
}

The testing is redundant. The read or write operations will return -1 if the other end closes or disconnects before or during the operation. There is no point in "testing" the connection first because it may subsequently fail during your IO operation.

See also the other answer mentioned in the comments.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM