简体   繁体   中英

TCP detect disconnected server from client

I'm writing a simple TCP client/server program pair in Java, and the server must disconnect if the client hasn't sent anything in 10 seconds. socket.setSoTimeout() gets me that, and the server disconnects just fine. The problem is - how can I get the client to determine if the server is closed? Currently I'm using DataOutputStream for writing to the server, and some answers here on SO suggest that writing to a closed socket will throw an IOException, but that doesn't happen.

What kind of writer object should I use to send arbitrary byte blocks to the server, that would throw an exception or otherwise indicate that the connection has been closed remotely?

Edit: here's the client code. This is a test function that reads one file from the file system and sends it to the server. It sends it in chunks, and pauses for some time between each chunk.

public static void sendFileWithTimeout(String file, String address, int dataPacketSize, int timeout) {
    Socket connectionToServer = null;
    DataOutputStream outStream = null;
    FileInputStream inStream = null;
    try {
        connectionToServer = new Socket(address, 2233);

        outStream = new DataOutputStream(connectionToServer.getOutputStream());

        Path fileObject = Paths.get(file);

        outStream.writeUTF(fileObject.getFileName().toString());

        byte[] data = new byte[dataPacketSize];

        inStream = new FileInputStream(fileObject.toFile());
        boolean fileFinished = false;
        while (!fileFinished) {
            int bytesRead = inStream.read(data);
            if (bytesRead == -1) {
                fileFinished = true;
            } else {
                outStream.write(data, 0, bytesRead);
                System.out.println("Thread " + Thread.currentThread().getName() + " wrote " + bytesRead + " bytes.");
                Thread.sleep(timeout);
            }
        }

    } catch (IOException | InterruptedException e) {
        System.out.println("Something something.");
        throw new RuntimeException("Problem sending data to server.", e);
    } finally {
        TCPUtil.silentCloseObject(inStream);
        TCPUtil.silentCloseObject(outStream);
        TCPUtil.silentCloseObject(connectionToServer);
    }
}

I'd expect the outStream.write to throw an IOException when it tries to write to a closed server, but nothing.

I'd expect the outStream.write to throw an IOException when it tries to write to a closed server, but nothing.

It won't do that the first time, because of the socket send buffer. If you keep writing, it will eventually throw an IOException: 'connection reset'. If you don't have data to get to that point, you will never find out that the peer has closed.

Remember ServerSocket.setSoTimeout() is different from client's function with same name.

For server, this function only throws SocketTimeoutException for you to catch it if timeout is expired, but the server socket still remains.

For client, setSoTimeout() relates to 'read timeout' for stream reading.

In your case, you must show your server code of closing the connected socket after catching SocketTimeoutException => ensure server closed the associated socket with a specified client. If done, at client side , your code line:

throw new RuntimeException("Problem sending data to server.", e);

will be called.

[Update]

I noticed that you stated to set timeout for the accepted socket at server side to 10 secs (=10,000 milliseconds); for that period, did your client complete all the file sending? if it did, never the exception occurs.

[Suggest]

for probing, just comment out your code of reading file content to send to server, and try replacing with several lines of writing to output stream:

outStream.writeUTF("ONE");
outStream.writeUTF("TWO");
outStream.writeUTF("TREE");

Then you can come to the conclusion.

I think you need to flush and close your stream after written like outStream.flush(); outStream.close(); inStream.close();

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