Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

First write to a remotely-closed socket does not trigger exception, can it? Java

I have not been able to find a satisfying answer to this question anywhere. Could someone with an understanding of the internals please explain this?

I wrote a simple client/server to demonstrate this issue. The server reads one line of text then closes the socket. The client writes one line of text, waits 10 seconds, then writes two more lines of text. The second write (after 10 seconds) fails but the first write always succeeds.

Why can't the BufferedWriter throw an exception on the first write itself? After all the socket was normally closed a long time before. The code also does a read on the socket right before the first write, returns -1 to show that the input side has already detected the socket close. Why can't the output side also know this?

  public class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket ss = new ServerSocket(9000);
        Socket s = ss.accept();
        BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
        System.out.println(in.readLine());
        s.close();
        System.out.println("Socket closed");
    }
  }

  public class Client {
    public static void main(String[] args) throws IOException, InterruptedException {
        Socket s = new Socket("localhost", 9000);
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
        out.write("Hello, World!\n"); out.flush();
        Thread.sleep(10000);
        System.out.println("Read from socket returns: " + s.getInputStream().read());
        out.write("First write\n"); out.flush();
        System.out.println("First write succeeded without detecting socket closed");
        out.write("Second write\n"); out.flush();
        System.out.println("Second write succeeded without detecting socket closed");
    }
  }
like image 363
Sarsaparilla Avatar asked Oct 05 '22 19:10

Sarsaparilla


1 Answers

A remote close is indistinguishable from a remote shutdown for output. This end receives a FIN in both cases, meaning the peer has stopped sending. There is no indication that he has stopped receiving, even in fact if he has shutdown for input. So the only way the sender can detect is by getting an RST on sending, and that can't happen on the first send, by definition, unless maybe the sent data is larger than the socket send buffer.

like image 145
user207421 Avatar answered Oct 10 '22 01:10

user207421