95

As a follow up to a recent question, I wonder why it is impossible in Java, without attempting reading/writing on a TCP socket, to detect that the socket has been gracefully closed by the peer? This seems to be the case regardless of whether one uses the pre-NIO Socket or the NIO SocketChannel.

When a peer gracefully closes a TCP connection, the TCP stacks on both sides of the connection know about the fact. The server-side (the one that initiates the shutdown) ends up in state FIN_WAIT2, whereas the client-side (the one that does not explicitly respond to the shutdown) ends up in state CLOSE_WAIT. Why isn't there a method in Socket or SocketChannel that can query the TCP stack to see whether the underlying TCP connection has been terminated? Is it that the TCP stack doesn't provide such status information? Or is it a design decision to avoid a costly call into the kernel?

With the help of the users who have already posted some answers to this question, I think I see where the issue might be coming from. The side that doesn't explicitly close the connection ends up in TCP state CLOSE_WAIT meaning that the connection is in the process of shutting down and waits for the side to issue its own CLOSE operation. I suppose it's fair enough that isConnected returns true and isClosed returns false, but why isn't there something like isClosing?

Below are the test classes that use pre-NIO sockets. But identical results are obtained using NIO.

import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {
  public static void main(String[] args) throws Exception {
    final ServerSocket ss = new ServerSocket(12345);
    final Socket cs = ss.accept();
    System.out.println("Accepted connection");
    Thread.sleep(5000);
    cs.close();
    System.out.println("Closed connection");
    ss.close();
    Thread.sleep(100000);
  }
}


import java.net.Socket;

public class MyClient {
  public static void main(String[] args) throws Exception {
    final Socket s = new Socket("localhost", 12345);
    for (int i = 0; i < 10; i++) {
      System.out.println("connected: " + s.isConnected() + 
        ", closed: " + s.isClosed());
      Thread.sleep(1000);
    }
    Thread.sleep(100000);
  }
}

When the test client connects to the test server the output remains unchanged even after the server initiates the shutdown of the connection:

connected: true, closed: false
connected: true, closed: false
...
Community
  • 1
  • 1
Alexander
  • 9,302
  • 2
  • 26
  • 22
  • I tought I would mention: The SCTP protocol doesn't have this "problem". SCTP doesn't have a half-closed state as TCP, in other words one side can not continue sending data while the other end has closed its sending socket. That should make things easier. – Tarnay Kálmán Apr 12 '09 at 07:34
  • 2
    We have two Mailboxes (Sockets)................................................. The Mailboxes send mail to eachother using the RoyalMail (IP) forget about TCP ................................................. All is fine and dandy, the mailboxes can send/recieve mail to eachother (loads of lag recently) sending while recieving no problem. ............. If one Mailbox was to get hit by a truck and fail.... how would the other Mailbox know? It would have to be notifyed by Royal Mail, who in turn wouldnt know untill it next tryed sending/recieving mail from that failed Mailbox.. ...... erm..... – divinci Nov 20 '09 at 22:28
  • If you're not going to read from the socket or write to the socket, why do you care? And if you are going to read from the socket or write to the socket, why do an extra check? What's the use case? – David Schwartz Mar 14 '14 at 23:27
  • 2
    `Socket.close` is not a graceful close. – user253751 May 10 '14 at 00:52
  • @immibis It most certainly is a graceful close, unless there is unread data in the socket receive buffer or you have messed with SO_LINGER. – user207421 Aug 15 '16 at 22:48

12 Answers12

29

I have been using Sockets often, mostly with Selectors, and though not a Network OSI expert, from my understanding, calling shutdownOutput() on a Socket actually sends something on the network (FIN) that wakes up my Selector on the other side (same behaviour in C language). Here you have detection: actually detecting a read operation that will fail when you try it.

In the code you give, closing the socket will shutdown both input and output streams, without possibilities of reading the data that might be available, therefore loosing them. The Java Socket.close() method performs a "graceful" disconnection (opposite as what I initially thought) in that the data left in the output stream will be sent followed by a FIN to signal its close. The FIN will be ACK'd by the other side, as any regular packet would1.

If you need to wait for the other side to close its socket, you need to wait for its FIN. And to achieve that, you have to detect Socket.getInputStream().read() < 0, which means you should not close your socket, as it would close its InputStream.

From what I did in C, and now in Java, achieving such a synchronized close should be done like this:

  1. Shutdown socket output (sends FIN on the other end, this is the last thing that will ever be sent by this socket). Input is still open so you can read() and detect the remote close()
  2. Read the socket InputStream until we receive the reply-FIN from the other end (as it will detect the FIN, it will go through the same graceful diconnection process). This is important on some OS as they don't actually close the socket as long as one of its buffer still contains data. They're called "ghost" socket and use up descriptor numbers in the OS (that might not be an issue anymore with modern OS)
  3. Close the socket (by either calling Socket.close() or closing its InputStream or OutputStream)

As shown in the following Java snippet:

public void synchronizedClose(Socket sok) {
    InputStream is = sok.getInputStream();
    sok.shutdownOutput(); // Sends the 'FIN' on the network
    while (is.read() > 0) ; // "read()" returns '-1' when the 'FIN' is reached
    sok.close(); // or is.close(); Now we can close the Socket
}

Of course both sides have to use the same way of closing, or the sending part might always be sending enough data to keep the while loop busy (e.g. if the sending part is only sending data and never reading to detect connection termination. Which is clumsy, but you might not have control on that).

As @WarrenDew pointed out in his comment, discarding the data in the program (application layer) induces a non-graceful disconnection at application layer: though all data were received at TCP layer (the while loop), they are discarded.

1: From "Fundamental Networking in Java": see fig. 3.3 p.45, and the whole §3.7, pp 43-48

Matthieu
  • 2,736
  • 4
  • 57
  • 87
  • Java does perform a graceful close. It is not 'brutal'. – user207421 Apr 14 '13 at 01:26
  • 2
    @EJP, "graceful disconnection" is a specific exchange taking place at TCP level, where the Client should signal its will to disconnect to the Server, which, in turn, sends remaining data before closing its side. The "send remaining data" part has to be handled by the program (though people wouldn't send anything most of the time). Calling `socket.close()` is "brutal" in the way it does not respect this Client/Server signaling. Server would be notified of a Client disconnection only when its own socket output buffer is full (because no data are being ack'ed by the other side, which was closed). – Matthieu Apr 14 '13 at 15:44
  • See [MSDN](http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspx) for more information. – Matthieu Apr 14 '13 at 15:44
  • Java doesn't force applications to call Socket.close() instead of 'send[ing] remaining data' first, and it doesn't prevent them from using a shutdown first. Socket.close() just does what close(sd) does. Java is no different in this respect from the Berkeley Sockets API itself. Indeed, in most respects. – user207421 May 21 '13 at 12:36
  • Exactly, I couldn't agree more! :) – Matthieu May 23 '13 at 10:45
  • Then why are you asserting the opposite? Socket.close() doesn't abort the connection, and your source doesn't say otherwise. Your source gives a nice way for both ends to achieve a *synchronized* close such that both peers know the other has all the data, but it doesn't say that data will be lost if you don't do it. Try it some time. You might get a surprise. – user207421 Aug 16 '13 at 22:25
  • `close()` *will* close both input and output streams so you won't be able to send/receive anything after you called it. The point in "graceful disconnection" is what you say: achieving synchronized close: the other side has all the data *and* you stop sending anything more. If you `close()` without doing so, you're closing the socket `InputStream` which is connected to the network interface internal buffer, which might contain data that haven't been processed yet. There you have data loss. The OS might let the Socket opened internally ("ghost" socket). Not a big deal on modern OS though... – Matthieu Aug 17 '13 at 05:57
  • I must add I prefer your terminology of "synchronized close" rather than "graceful disconnection". It tells more about the algorithm of terminating a network connection. – Matthieu Aug 17 '13 at 05:59
  • @EJP (sorry I forgot to mention your name in my previous comments), it looks like 'close()' is performing both 'shutdownOutput()'/'shutdownInput()'. Now I understand your concern, as a FIN will actually be sent. To me, "graceful" meant what you called "synchronized": both sockets ACKed their disconnection *and* have empty input and output buffers. – Matthieu Sep 18 '13 at 21:51
  • No. 'Graceful close' means that all data is delivered, *followed by* an EOS indication. SPX for example didn't have a graceful close: any data in flight could be just lost; and it was 100% useless as a result of that and other deficiencies. This is also what happens when a TCP connection is reset rather than closed. These terms already have meanings. Don't reinvent them please. And please edit the misinformation about 'brutal close' out of your answer. – user207421 Sep 18 '13 at 22:33
  • @EJP I edited, please tell me if it sounds better. But then what happens when one side calls 'close' on its socket while data are still waiting to be read in its queue? To me it's not a graceful close, though data were delivered (to the remote hardware) but will be lost still. – Matthieu Sep 20 '13 at 17:21
  • 1
    @Matthieu If your application doesn't read all available data, that may be ungraceful at the application layer, but at the TCP transport layer, the data is still received and the connection terminated gracefully. The same would be true if your application read all the data out of the input stream and merely discarded it. – Warren Dew May 18 '14 at 06:07
  • @WarrenDew exactly. That might have been the point(s) raised by EJP in his comments: to me, "graceful" is at network (TCP) level, not Application. What happens in the application is (should be) up to the program only. I'll edit my answer to add that information. – Matthieu May 19 '14 at 07:35
  • @WarrenDew That's not correct. If the application closes the socket while there is still data in the socket receive buffer, the connection will be reset, not closed with a FIN. – user207421 Apr 20 '16 at 00:01
  • @EJP even if `shutdownOutput()` is called? – Matthieu Apr 22 '16 at 15:40
  • @Mattheiu If the application calls `shutdownOutout()` and then `close()` when there is unread data in the socket receive buffer, a FIN will be sent followed by an RST. The claim that Java does not perform a graceful disconnect in your answer remains incorrect. – user207421 Sep 13 '16 at 23:37
  • @EJP thank you for that additional information, it starts making sense (4 years later...). It seems my asumptions are technically incomplete and my wording is imprecise so I'll probably ask a separate question later to clarify further. Thank you for not giving up pushing both into my (hard) head! – Matthieu Sep 14 '16 at 14:29
  • Your answer remains nonsense starting from the second paragraph. Please fix it. – user207421 Dec 15 '16 at 04:27
  • @EJP, I do agree and did a fix attempt. I'd love to read your comments about it. – Matthieu Dec 15 '16 at 21:10
  • 2
    @LeonidUsov That is simply incorrect. Java `read()` returns -1 at end of stream, and continues to do so however many times you call it. A C `read()` or `recv()` returns zero at end of stream, and continues to do so however many times you call it. – user207421 Jun 13 '17 at 09:44
  • @Matthieu 'Without possibilities of reading the data that might be available' remains incorrect. No data is discarded by a graceful close, as I first stated over four years ago, and in my book as well. And anything that is read by `read()` after shutdown basically constitutes an application protocol error and should be reported and debugged, not ignored. – user207421 Jun 13 '17 at 09:49
  • @EJP the tests I ran show if you `close()` or `shutdownInput()` a socket, a call to `read()` throws a `SocketException` stating `Socket is closed` or `Socket input is shutdown`, even though there *is* data in its input buffer. I don't know how to access that data *after* the socket has been closed or shutdown... – Matthieu Jun 15 '17 at 13:18
19

I think this is more of a socket programming question. Java is just following the socket programming tradition.

From Wikipedia:

TCP provides reliable, ordered delivery of a stream of bytes from one program on one computer to another program on another computer.

Once the handshake is done, TCP does not make any distinction between two end points (client and server). The term "client" and "server" is mostly for convenience. So, the "server" could be sending data and "client" could be sending some other data simultaneously to each other.

The term "Close" is also misleading. There's only FIN declaration, which means "I am not going to send you any more stuff." But this does not mean that there are no packets in flight, or the other has no more to say. If you implement snail mail as the data link layer, or if your packet traveled different routes, it's possible that the receiver receives packets in wrong order. TCP knows how to fix this for you.

Also you, as a program, may not have time to keep checking what's in the buffer. So, at your convenience you can check what's in the buffer. All in all, current socket implementation is not so bad. If there actually were isPeerClosed(), that's extra call you have to make every time you want to call read.

dty
  • 18,795
  • 6
  • 56
  • 82
Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319
  • 1
    I don't think so, you can test for states in C code on both windows and linux!!! Java for some reason may not expose some of the stuff, like it would be nice to expose the getsockopt functions that are on windows and linux. In fact, answers below have some linux C code for the linux side. – Dean Hiller Aug 24 '12 at 17:56
  • I do not think that having 'isPeerClosed()' method somehow commits you to call it before every read attempt. You can simply call it only when you explicitly need it. I agree that current socket implementation is not so bad, even though it requires you to write to output stream if you want to find out whether the remote part of socket is closed or not. Because if it is not, you have to handle your written data on the other side as well, and it is simply as large amount of pleasure as sitting on the vertically oriented nail;) – Jan Hruby Jan 15 '13 at 14:43
  • 1
    It *does* mean 'there is no more packet in flight'. The FIN is received *after* any data in flight. However what it *doesn't* mean is that the peer has closed the socket *for input.* You have to ***send* something* and get a 'connection reset' to detect that. The FIN could have just meant a shutdown for output. – user207421 Jun 04 '14 at 10:32
11

The underlying sockets API doesn't have such a notification.

The sending TCP stack won't send the FIN bit until the last packet anyway, so there could be a lot of data buffered from when the sending application logically closed its socket before that data is even sent. Likewise, data that's buffered because the network is quicker than the receiving application (I don't know, maybe you're relaying it over a slower connection) could be significant to the receiver and you wouldn't want the receiving application to discard it just because the FIN bit has been received by the stack.

Mike Dimmick
  • 9,662
  • 2
  • 23
  • 48
  • In my test example (maybe I should provide one here...) there's no data sent/received over the connection on purpose. So, I'm pretty sure the stack receives the FIN (graceful) or RST (in some non-graceful scenarios). This is also confirmed by netstat. – Alexander Sep 30 '08 at 22:16
  • 1
    Sure - if nothing's buffered then the FIN will be sent immediately, on an otherwise empty packet (no payload). After FIN, though, no more data packets are sent by that end of the connection (it will still ACK anything sent to it). – Mike Dimmick Sep 30 '08 at 22:46
  • 1
    What happens is that the sides of the connection end up in CLOSE_WAIT and FIN_WAIT_2 and it is in this state the isConcected() and isClosed() still don't see that the connection has been terminated. – Alexander Sep 30 '08 at 22:49
  • Thanks for your suggestions! I think I understand the issue better now. I made the question more specific (see third paragraph): why isn't there "Socket.isClosing" to test for half-closed connections? – Alexander Sep 30 '08 at 23:26
8

Since none of the answers so far fully answer the question, I'm summarizing my current understanding of the issue.

When a TCP connection is established and one peer calls close() or shutdownOutput() on its socket, the socket on the other side of the connection transitions into CLOSE_WAIT state. In principle, it's possible to find out from the TCP stack whether a socket is in CLOSE_WAIT state without calling read/recv (e.g., getsockopt() on Linux: http://www.developerweb.net/forum/showthread.php?t=4395), but that's not portable.

Java's Socket class seems to be designed to provide an abstraction comparable to a BSD TCP socket, probably because this is the level of abstraction to which people are used to when programming TCP/IP applications. BSD sockets are a generalization supporting sockets other than just INET (e.g., TCP) ones, so they don't provide a portable way of finding out the TCP state of a socket.

There's no method like isCloseWait() because people used to programming TCP applications at the level of abstraction offered by BSD sockets don't expect Java to provide any extra methods.

Alexander
  • 9,302
  • 2
  • 26
  • 22
  • 3
    Nor *can* Java provide any extra methods, portably. Maybe they could make an isCloseWait() method which would return false if the platform didn't support it, but how many programmers would be bitten by that gotcha if they only tested on supported platforms? – ephemient Oct 10 '08 at 17:53
  • 1
    looks like it could be portable to me...windows has this http://msdn.microsoft.com/en-us/library/windows/desktop/ms738544(v=vs.85).aspx and linux this http://pubs.opengroup.org/onlinepubs/009695399/functions/getsockopt.html – Dean Hiller Aug 24 '12 at 15:58
  • 1
    It's not that programmers are used to it; it's that the socket interface is what's useful to programmers. Keep in mind that the socket abstraction is used for more than the TCP protocol. – Warren Dew May 18 '14 at 06:09
  • There's no method in Java like `isCloseWait()` because it isn't supported on all platforms. – user207421 Jun 04 '14 at 10:40
  • The ident (RFC 1413) protocol allows the server to either keep the connection open after sending a response, or close it without sending any more data. A Java ident client might choose to keep the connection open to avoid the 3-way handshake on the next lookup, but how does it know the connection is still open? Should it just try, respond to any error by reopening the connection? Or is that a protocol design error? – david May 22 '15 at 19:35
  • @david It knows because another send succeeds and another receive doesn't return a premature end of stream. – user207421 Jun 13 '17 at 09:50
7

Detecting whether the remote side of a (TCP) socket connection has closed can be done with the java.net.Socket.sendUrgentData(int) method, and catching the IOException it throws if the remote side is down. This has been tested between Java-Java, and Java-C.

This avoids the problem of designing the communication protocol to use some sort of pinging mechanism. By disabling OOBInline on a socket (setOOBInline(false), any OOB data received is silently discarded, but OOB data can still be sent. If the remote side is closed, a connection reset is attempted, fails, and causes some IOException to be thrown.

If you actually use OOB data in your protocol, then your mileage may vary.

Uncle Per
  • 71
  • 1
  • 1
4

the Java IO stack definitely sends FIN when it gets destructed on an abrupt teardown. It just makes no sense that you can't detect this, b/c most clients only send the FIN if they are shutting down the connection.

...another reason i am really beginning to hate the NIO Java classes. It seems like everything is a little half-ass.

  • 1
    also, it appears I only get and end-of-stream on read (-1 return) when a FIN is present. So this is the only way i can see to detect a shutdown on the read side. –  Jul 06 '09 at 03:46
  • 3
    You can detect it. You get EOS when reading. And Java doesn't send FINs. TCP does that. Java does not implement TCP/IP, it just uses the platform implementation. – user207421 Aug 16 '13 at 22:22
4

It's an interesting topic. I've dug through the java code just now to check. From my finding, there are two distinct problems: the first is the TCP RFC itself, which allows for remotely closed socket to transmit data in half-duplex, so a remotely closed socket is still half open. As per the RFC, RST doesn't close the connection, you need to send an explicit ABORT command; so Java allow for sending data through half closed socket

(There are two methods for reading the close status at both of the endpoint.)

The other problem is that the implementation say that this behavior is optional. As Java strives to be portable, they implemented the best common feature. Maintaining a map of (OS, implementation of half duplex) would have been a problem, I guess.

user207421
  • 305,947
  • 44
  • 307
  • 483
Lorenzo Boccaccia
  • 6,041
  • 2
  • 19
  • 29
  • 1
    I suppose you're talking about RFC 793 (http://www.faqs.org/rfcs/rfc793.html) Section 3.5 Closing a Connection. I'm not sure it explains the issue, because both sides complete the graceful shutdown of the connection and end up in states where they shouldn't send/receive any data. – Alexander Sep 30 '08 at 22:34
  • Depends. how many FIN you see on the socket? Also, could be a platform specific problem: maybe windows replies each FIN with a FIN and the connection is closed on both ends, but other operating systems may not behave this way, and this is where problem 2 arises – Lorenzo Boccaccia Sep 30 '08 at 22:41
  • I only see one FIN sent by the server-side (the one that initiates the shutdown). I've updated the question with the TCP states. The behavior seems to be indentical between Windows XP and Linux 2.6. – Alexander Sep 30 '08 at 23:06
  • Thanks for your suggestions! I think I understand the issue better now. I made the question more specific (see third paragraph): why isn't there "Socket.isClosing" to test for half-closed connections? – Alexander Sep 30 '08 at 23:15
  • because there is isOutputShutdown() and isInputShutdown(); don't know if those are fully working, however. (as usual they depends of the actual implementation of the standard inside the OS, and inside the JVM) – Lorenzo Boccaccia Sep 30 '08 at 23:17
  • 1
    No, unfortunately that's not the case. isOutputShutdown and isInputShutdown is the first thing everyone tries when faced with this "discovery", but both methods return false. I've just tested it on Windows XP and Linux 2.6. The return values of all 4 methods remain the same even after a read attempt – Alexander Sep 30 '08 at 23:25
  • question (this problem bite me time ago, and I normally work around it, but now that we are there...): did you tried out other jvm (kaffe, gcj, etc)? – Lorenzo Boccaccia Sep 30 '08 at 23:35
  • Ran a quick test: same story in Blackdown 1.4.1 on Linux 2.6 – Alexander Sep 30 '08 at 23:53
  • Java needs to implement http://msdn.microsoft.com/en-us/library/windows/desktop/ms738544(v=vs.85).aspx and http://pubs.opengroup.org/onlinepubs/009695399/functions/getsockopt.html to make us all happy so we can find out the states of the socket on our end. – Dean Hiller Aug 24 '12 at 16:00
  • @LorenzoBoccaccia The shutdown methods are fully implemented. – user207421 Apr 14 '13 at 01:30
  • Very confused answer. The RFC does not allow a remotely closed socket to keep sending data. If you get RST, it means there is no such connection at the peer, and it aborts the connection at your end. The RFC doesn't say anything different. – user207421 Apr 14 '13 at 01:38
  • 1
    For the record, this is not half-duplex. Half-duplex means only one side can send at s time; both sides can still send. – rbp May 18 '13 at 22:54
  • 1
    isInputShutdown and isOutputShutdown test the *local* end of the connection - they are tests to find out whether you've called shutdownInput or shutdownOutput on this Socket. They don't tell you anything about the remote end of the connection. – Mike Dimmick Aug 22 '13 at 17:51
3

This is a flaw of Java's (and all others' that I've looked at) OO socket classes -- no access to the select system call.

Correct answer in C:

struct timeval tp;  
fd_set in;  
fd_set out;  
fd_set err;  

FD_ZERO (in);  
FD_ZERO (out);  
FD_ZERO (err);  

FD_SET(socket_handle, err);  

tp.tv_sec = 0; /* or however long you want to wait */  
tp.tv_usec = 0;  
select(socket_handle + 1, in, out, err, &tp);  

if (FD_ISSET(socket_handle, err) {  
   /* handle closed socket */  
}  
Blazor
  • 171
  • 4
  • 11
Joshua
  • 40,822
  • 8
  • 72
  • 132
  • You can do the same thing with `getsocketop(... SOL_SOCKET, SO_ERROR, ...)`. – David Schwartz Oct 21 '11 at 00:38
  • YEAH. and that seems to exist on windows AND on linux both!!!! http://pubs.opengroup.org/onlinepubs/009695399/functions/getsockopt.html and http://msdn.microsoft.com/en-us/library/windows/desktop/ms738544(v=vs.85).aspx ...it is all java's fault :( – Dean Hiller Aug 24 '12 at 15:59
  • 1
    Error file descriptor set won't indicate closed connection. Please read select manual: 'exceptfds - This set is watched for "exceptional conditions". In practice, only one such excetional condition is common: the availability of out-of-band (OOB) data for reading from a TCP socket.' FIN is not OOB data. – Jan Wrobel Sep 09 '12 at 21:11
  • Yeah it turned out graceful closed shows up as able to read not except. I always wrote my code as if either, try read (and we know it won't block) and I never used OOB. – Joshua Sep 11 '12 at 02:48
  • This didn't actually detect a closed socket for me (using QNX). I found this http://stackoverflow.com/a/5640189/1326370 worked for me. – sclarke81 Jul 15 '13 at 08:28
  • Topologically equivalent. – Joshua Jul 15 '13 at 15:27
  • 1
    You can use 'Selector' class to access 'select()' syscall. It uses NIO though. – Matthieu Sep 18 '13 at 21:34
  • 1
    There is nothing exceptional about a connection that has been shutdown by the other side. – David Schwartz Mar 14 '14 at 23:26
  • 1
    Many platforms, *including* Java, *do* provide access to the select() system call. – user207421 Jun 04 '14 at 10:39
2

Here is a lame workaround. Use SSL ;) and SSL does a close handshake on teardown so you are notified of the socket being closed (most implementations seem to do a propert handshake teardown that is).

Dean Hiller
  • 19,235
  • 25
  • 129
  • 212
2

The reason for this behaviour (which is not Java specific) is the fact that you don't get any status information from the TCP stack. After all, a socket is just another file handle and you can't find out if there's actual data to read from it without actually trying to (select(2) won't help there, it only signals that you can try without blocking).

For more information see the Unix socket FAQ.

user207421
  • 305,947
  • 44
  • 307
  • 483
WMR
  • 12,661
  • 5
  • 35
  • 30
  • 2
    REALbasic sockets (on Mac OS X and Linux) are based on BSD sockets, yet RB manages to give you a nice error 102 when the connection is dropped by the other end. So I agree with the original poster, this should be possible and it's lame that Java (and Cocoa) don't provide it. – Joe Strout May 12 '10 at 20:41
  • 1
    @JoeStrout RB can only do that when you do some I/O. There is no API that will give you to status of the connection without doing I/O. Period. This is not a Java deficiency. It is in fact due to the lack of a 'dial tone' in TCP, which is a deliberate design feature. – user207421 Aug 16 '13 at 22:20
  • `select()` tells you whether there is data or EOS available to be read without blocking. 'Signals that you can try without blocking' is meaningless. If you're in non-blocking mode, you can *always* try without blocking. `select()` is driven by data in the socket receive buffer or a pending FIN or space in the socket send buffer. – user207421 Feb 25 '16 at 22:24
  • @EJP What about `getsockopt(SO_ERROR)`? In fact, even `getpeername` will tell you if the socket is still connected. – David Schwartz Sep 13 '16 at 21:51
0

Only writes require that packets be exchanged which allows for the loss of connection to be determined. A common work around is to use the KEEP ALIVE option.

Ray
  • 106
  • 1
  • 6
  • I think an endpoint is allowed to initiate a graceful connection shutdown by sending a packet with FIN set, without writing any payload. – Alexander Oct 10 '08 at 23:35
  • @Alexander Of course it does, but that isn't relevant to this answer, which is about *detecting* less of connection. – user207421 Aug 15 '16 at 22:51
-3

When it comes to dealing with half-open Java sockets, one might want to have a look at isInputShutdown() and isOutputShutdown().

JimmyB
  • 12,101
  • 2
  • 28
  • 44