Java writing to closed output stream not throwing ioexception
Asked Answered
W

2

6

Here is the flow of my client/server.

Socket is created in main thread.

  1. Socket passes to Thread 1.
  2. Client sends data to server
  3. Server responds to client
  4. Server closes input stream, output stream, and socket by invoking close()
  5. Socket returned to main thread, and then passed to Thread 2.
  6. Client writes data to server - no exception, no errors, server gets no data
  7. Client attempts to read data - no exceptions, no errors

How can I detect the problem that socket was closed?

try {
        os = new DataOutputStream(this.socket.getOutputStream());
        os.write(data);
        os.flush();
        System.out.println("Written " + data.length + " bytes");
    } catch (IOException e) {
        System.out.println("Client failed to write to stream");
        System.out.println(e.getMessage());
        e.printStackTrace();
    }

The exception is never thrown. It says Written 60 bytes. Any ideas?


UPDATE

Here is the way that I read the response. I wait for data, read first 4 bytes (which gives the the length of response), and keep reading until I read the specified length. This loop never ends because no data ever comes in.

is = new DataInputStream(this.socket.getInputStream());
    while(true){
        while(is.available() > 0){
            bos.write(is.read());
        }
        if(contentLength == 0 && bos.size() > 3){
            byte[] bytes = bos.toByteArray();
            byte[] size = Arrays.copyOf(bytes, 4);
            contentLength = ByteBuffer.wrap(size).getInt();
        }
        if(bos.size() - 4 < contentLength){
            continue;
        }
        break;
    }
Wald answered 22/7, 2016 at 19:9 Comment(4)
have you checked SocketException? if you are closing everything then it should throw that also.Annabellannabella
yes, no exception is thrown. i updated the question with additional information about the sockets being passed between threadsWald
How many bytes can you read from a closed stream without blocking? None. So available() must return zero.Umbilication
You are not writing to a closed output stream. You are writing to a connection which may have been closed by the peer. It isn't the same thing.Stochmal
F
2

When the server closes its end of the TCP connection, it sends a FIN packet to tell the client. The client program sees this as the InputStream reaching the end. Also, if the client tries to write the server will send an RST packet to signal error. If the client program tries to write after RST was received, the API will throw a SocketException with the message "connection reset."

Your problem is with detecting the end of the input here:

    while(is.available() > 0){
        bos.write(is.read());
    }

The available method probably doesn't do what you think it does. If you want to read 4 bytes, read 4 bytes:

byte[] bytes = new byte[4];
is.readFully(bytes); // throws EOFException on end of input
Fabria answered 23/7, 2016 at 6:53 Comment(0)
E
1

It says that it wrote 60 bytes because it did. The server just isn't listening anymore. You need to get the input stream to see if anything is there. If nothing comes back, then you know that the connection didn't work.

UPDATE

Use a timer to determine if the server is responding.

Long currenttime = System.currentTimeMillis();
while(System.currentTimeMillis() - currentTime < x){ //x = miliseconds you want to wait
    (try to read from server)
}

This way if it takes longer than x seconds, it will time out and you can do some error catching after the while loop

Eustazio answered 22/7, 2016 at 19:15 Comment(1)
ok i see. im gonna update my question with the method that i read data, that may be the culprit here.Wald

© 2022 - 2024 — McMap. All rights reserved.