Link to home
Start Free TrialLog in
Avatar of adlabac
adlabacFlag for Montenegro

asked on

TCP/IP disconnection detection

Hi,

I am writing some Telnet client and I have a problem. Namely, I found no way to detect when server disconnect me (other than to send a few strings and wait for exception). Here is the code:

public static void main(String[] args)
{
    Socket socket;
    InputStream in;
    OutputStream out;

    try
    {
        socket = new Socket("192.168.81.146",23);
        in = socket.getInputStream();
        out = socket.getOutputStream();
        BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
        boolean theEnd = false;

        while(!theEnd)
        {
            try
            {
                if (keyboard.ready())
                {
                    String command = keyboard.readLine();
                    command = command + "\r";
                    out.write(command.getBytes());
                    out.flush();
                }
            }
            catch (IOException e)
            {
                kraj = true;
                System.err.println (e);
            }
            if (in.available() > 0)
            {
                byte[] b = new byte[in.available()];
                int len = in.read(b);
                String text = new String (b,0,len);
                System.out.print (text);
            }
            try
            {
                Thread.sleep(100);
            }
            catch (InterruptedException ie)
            {
                return;
            }
            if (!socket.isBound() || !socket.isConnected() || socket.isClosed() ||
                 socket.isInputShutdown() || socket.isOutputShutdown()) theEnd = true;
        }
        in.close();
        out.close();
        socket.close();
    }
    catch (IOException ioe)
    {
        System.err.println (ioe);
    }
}

None of the methods used to detect if the connection is active (isBound, isConnected, isClosed, isInputShutdown, isOutputShutdown) worked, though the connection is down. I tried to set the timeout to 25, but nothing happened.

Any ideas?

Best regards,
  Sasha
Avatar of krakatoa
krakatoa
Flag of United Kingdom of Great Britain and Northern Ireland image

You n
Sorry ... seem to be mistreating my mouse today!

The setKeepAlive() method is meant to exchange control messages across an idle socket and allow the client to determine whether the server has crashed without closing the socket - and vice versa.
Avatar of adlabac

ASKER

Nothing... I Added the following lines after creating the socket:

    socket = new Socket("192.168.81.146",23);  // already existed
    socket.setSoTimeout(25);
    socket.setKeepAlive(true);

Nothing happened.

Best regards,
  Sasha
Did you catch and handle the SocketException from getKeepAlive()?
Avatar of adlabac

ASKER

Why should I? Here is the code of getKeepAlive():

public boolean getKeepAlive() throws SocketException {
    if (isClosed())
        throw new SocketException("Socket is closed");
    return ((Boolean) getImpl().getOption(SocketOptions.SO_KEEPALIVE)).booleanValue();
}

Exception is thrown if connection isClosed, but it never is (after I open it). Furthermore, it returns the state of the field I set wih setKeepAlive(true).

Anyway, no exception happened at all.

Best regards,
  Sasha
1.
>> Why should I?

Because that is precidely what you are trying to trap - ie, is the connection alive or not - yes or no!

2.
You dont write your own method, you assign the bool that getKeepAlive() returns to a variable, to test for true or false, or just read the return value from it vanilla-like.

3.

>>Anyway, no exception happened at all.


You are looking for the exception covered by the property accessor method, not your method.

Avatar of adlabac

ASKER

You did not understand. I show the *real* code of getKeepAlive() method from java.net.Socket.class! All it does is checking if connection was establishes (in which case it raises SocketException) and returnes the value of SocketOptions.SO_KEEPALIVE, which is set via setKeepAlive() mothod!

If you try the code (or write your own) you'll see how it works.

Best regard,
  Sasha
Sorry, dont follow any of your last comments at all. :(
Avatar of adlabac

ASKER

In short - getKeepAlive() from java.net.Socket class does no work - it only returns the status which is set via setKeepAlive() method. It throws exception only if you never connected.

Best regards,
  Sasha
You are faced with several problems determining if a connection is open. The only reliable way is to poll it. To do that, you just need to test the reader/writer that you are using - that's how I did it in my client/server app., and that seems to work.

The problem is you cant have one process keep another one from losing its connection, because ultimately the connection is physical, and even the local machine cant legislate for physical disconn events. So all you can do is to test the socket, by seeing if you can read and/or write to it. Thats about as far as you can go AFAIK in pure Java.
Avatar of adlabac

ASKER

That I allready know, but there is a problem. Namely, I need to listen the phone switch. That means that I send some commands (including username and password) and just listen the aswers. That may last for hours. Now, if switch disconnects there is no obvious way to determine it - I do not sent anything and I am just waiting for the answer which will never come.

I don't see a reason for this. In other languages, when connection is lost I immediately receive a confirmation. In any case, connected state will return false if I check it. If it is right that I cannot know if I am still conected to other computer, than the fact that TCP/IP is embeded in Java by definition is ridiculous.

Best regards,
  Sasha
>>I need to listen the phone switch ....

This I do not understand.

Let's be clear and simple: whatever situation arises, as far as Java is concerned the only thing that counts is whether or not the socket can be read/written. There *is* a way to determine whether the socket is disconnected because I have written such a routone into my own programmes.

The "connected state" returning false, as you say: if you are talking about the getKeepAlive() again, then forget this at the moment. You need to write a "handler" for the socket which effectively polls and catches the exception that a disconn will throw. Have you tried to code that yet??

Avatar of adlabac

ASKER

> You need to write a "handler" for the socket which effectively polls and catches the
> exception that a disconn will throw. Have you tried to code that yet??

Can you be more specific. Let me note, again, that I cannot send anything after the handshake - just listen.

I wrote many programs which involved TCP/IP, many of them in use in the greatest GSM mobile operator in my country for years, without service. Now, I am trying to do the simpliest thing in Java - to listen to the port and to finish when the server disconnect me. This should be very simple. But, it looks that so simple task as checking if connection is still "alive" it is very poorly done in Java.

I would appreciate if you give me the sample how you did it. Remember - no sending, just receiving the data.

Best regards,
  Sasha
All you need to do is to write a routine that reads or writes to the socket. There is nothing else to it than that. I dont see what your problem is.

A read from the socket using BufferedReader will for example block until there is something to read. Writing to a socket will also show you whether the connection is open or not. Why cant you do that?
Avatar of adlabac

ASKER

As you can se from the source above, I constantly do this (every 100ms):

   if (in.available() > 0)
   {
       byte[] b = new byte[in.available()];
       int len = in.read(b);
       String text = new String (b,0,len);
       System.out.print (text);
   }

InputStream.available() returns 0 although there is no connection anymore!

I cannot write, because the telephone switch is on the other side awaiting for the command, and must not send any. Anyway, even if I send something nothing will happen, even if the connection is down! Only afrer two or three attempts to write something exception occurs!!!

Best regards,
  Sasha
in.available() should throw an IOException. I dont know where your code is situated in your programme, but if any exception that is being thrown by it is being caught elsewhere by another handler, then your in int is probably the one from the previous read, before the socket went down.
Avatar of adlabac

ASKER

But it does not! in.available() just returns 0! The whole application (i.e. main method) is shown above.

Best regards,
  Sasha
Some points here (working on the assumption that you're simply interested in reading when there's data to read)

1. If you're reading Strings, as you seem to be from your last posting, use a BufferedReader, then
>>String text = new String (b,0,len);

would become

String text = in.readLine();

2. But, loop, then repeat

while (keepReading) {
      String text = null;
      while ((text = in.readLine) != null) {
            System.out.print (text);
      }
      Thread.sleep(100);
}      

3. If you catch SocketException in there, you should be informed when there's been an abrupt termination of TCP/IP
Avatar of adlabac

ASKER

I used Strings only as an example. Actually I am reading a binary data (I already told that I am communicating with telephone switch). So BufferedREader wont do. Anyway, how can I use Buffered reader with Socket?

Best regards,
  Sasha
In this part of your code :

>>
if (in.available() > 0)
           {
               byte[] b = new byte[in.available()];
               int len = in.read(b);
               String text = new String (b,0,len);
               System.out.print (text);
           }
<<

the read(b) can be wrapped in a try - catch IOException. If one is thrown, then as far as the client is concerned, the server is down.
OK another thought just occured to me:

If your server is not sending (or does not have a chance to send) any data, and you are expecting to detect it losing its network connection from inside your client, then, as far as I know this will be impossible until your client tries to make a read from the socket. Detecting whether a remote  machine is down is, per se, not do-able in Java unless you try to make use of the socket.
Since the in.read(b) will block until something is available, you cant expect it to know if the server is disconnected while its waiting. You should make another thread which monitors the client/server socket (perhaps by testing the getKeepAlive() value), and get that thread to report the outage, and to optionally end your main thread.
Avatar of adlabac

ASKER

But, as I already said a for few times, getKeepAlive() returns the parameter you set by setKeepAlive, nothing more.

Best regards,
  Sasha
I dont think I can help you with this any further unless you tackle the points I am raising and answer my questions. Can you supply an answer to my comment of 09/17/2003 02:01AM PDT? Is that what you are trying to achieve?

As far as getKeepAlive() is concerned, a) have you tried putting it in a separate thread? b) have you tried reading from the socket and catching the exception?
Avatar of adlabac

ASKER

This will never end... Anyway, here are the answers/comments:

> the read(b) can be wrapped in a try - catch IOException.

I know how to catch exception. No exception occurs. Moreover, read(b) is newer called after the connection is down, because in.available() returns 0 in that case.

> as far as I know this will be impossible until your client tries to make a read from the socket

I must chect isAvailable() first. Othervise the exception will occur if there is nothing to read. isAvailable(), once more, is returning 0 if connection is down - no exceptions.

Best regards,
  Sasha
>> I must chect isAvailable() first

Why?? ***This is my point***. You should be trying to capture the exception that will be thrown *when read()* blows up!!

Forget about isAvailable() altogether.
You are trying to have your cake and eat it too with this. You ***cant*** determine if a socket is down unless you read or write to it, and if there is no data to be read or written, then you can *****never***** tell whether the connection is down or not. SetKeepAlive() will throw an exception if it ***cant** BE SWITCHED ON.
>>Actually I am reading a binary data (I already told that I am communicating with telephone switch). So BufferedREader wont do.

Then use a BufferedInputStream with the code i gave you instead and capture the data you read through that (i don't know what you're doing with the data)

>> Anyway, how can I use Buffered reader with Socket?

You can use a BufferedReader with any InputStream
Avatar of adlabac

ASKER

krakatoa> Why?? ***This is my point***. You should be trying to capture
krakatoa> the exception that will be thrown *when read()* blows up!!

Are you reading my comments at all. A told you thar read() will ***blow up*** even if connection is ***active*** and there is ***nothing to read***!

Best regards,
  Sasha
If the connection is active and read is called on the socket's input stream, the call will block until there are data to read
>> A told you thar read() will ***blow up***

yeah, where did you say that?
Try this:

kingdomcome=true;

public void getMeHookedUp(){
while(kingdomcome){
try{
sock = new Socket("192.168.81.146",23);
}catch(IOException nosock){System.out.println("Doh. Server still out.");sock=null;System.gc();getMeHookedUp();}

sockup=true;

while (sockup){
    try{
       sock.setKeepAlive(!(sock.getKeepAlive());
    }
    catch(SocektException sockex){sockup=false;}

    try{
       Thread.sleep(5000);
    }catch(InterruptedException dontbustinlikethat){}
  }
 }
}
Avatar of adlabac

ASKER

> If the connection is active and read is called on the socket'
> input stream, the call will block until there are data to read

No, if you use BufferedReader, but will if you use InputStream.

Best regards,
  Sasha
Avatar of adlabac

ASKER

>> A told you thar read() will ***blow up***

> yeah, where did you say that?

Look a few comments above. There says:

"I must chect isAvailable() first. Othervise the exception will occur if there is nothing to read. isAvailable(), once more, is returning 0 if connection is down - no exceptions."

Best regards,
  Sasha
Avatar of adlabac

ASKER

krakatoa> Try this:

I tried - nothing happened.

Best regards,
  Sasha
OK look, my own programme is able to detect dropped hosts reliably I believe. I cant see through your problem any further, probably because there is either something I stupidly misunderstood, or this "telephone switch" or whatever it is, is interfering.

What we can do is for you to get my clientside app., and we run it through my server. I will launch *two* clients at my end, one of which I will make physically lose its TCPIP connection. My remaining client, and your client, should then be notified a few seconds later, that my second client died.

If this works, I will be able to reiterate with greater certainty which - if any - of the points I have already made above are cogent. If it doesnt work, then it will show that it is not a TCPIP problem in the first place (or that it is one, but one which cannot be resolved in software).

If you want to try this, then post, and we'll set it up.
Avatar of adlabac

ASKER

OK, we can try.

Say, I will send you a text (e.g. "Hello!"). Then, you will send me some text for a few times (with pause for a few seconds in between) and disconnect me afterwards. Just for a check, before disconection send me appropriate text, like "Go away!".

Thank you.

Best regards,
  Sasha
Avatar of adlabac

ASKER

Just to mention - when I connect to the mentionwd switch via Telnet (Windows') or via my Delphi application it detects disconnection immediately, so I am pretty sure that the problem is not in TCP/IP communication, but in Socket.

Best regards,
  Sasha
Sasha, we dont need to worry about about what we say, if and when the connection is made. There are a couple of things to do before we get there, and other time for details like that. First :

1. I need to know where I can email you the client files.
2. You can tell me 1. by emailing me at : xco mms att f utu re mi nds dot com
3. get rid of all the spaces in the address at 2.  above. Replace the word att with @. Replace word dot with "."
4. you need >= java 1.4.1 runtime

the rest'll get sorted.

In the meantime,  I was just about to post you this:


>> I tried - nothing happened.

And in between times you can try :

kingdomcome=true;

public void getMeHookedUp(){
while(kingdomcome){
try{
System.out.println("Waiting for Server to Connect ...");
sock = new Socket("192.168.81.146",23);
System.out.println("Connection Established.");
}catch(IOException nosock){System.out.println("Doh. Server still out.");sock=null;System.gc();getMeHookedUp();}

sockup=true;

while (sockup){
   try{

      sock.setKeepAlive(!(sock.getKeepAlive());
   }
   catch(SocektException sockex){sockup=false;}

   try{
      Thread.sleep(5000);
   }catch(InterruptedException dontbustinlikethat){}
 }
}
}

You need to see "Connection Established." printed to your console.


OK, let me know.
Avatar of adlabac

ASKER

I corrected your code, because there was some sintax and semantic mistakes (for example the declaration of sock variable. Here is the code:

=================================================
import java.net.Socket;
import java.net.SocketException;
import java.io.*;

public class Krakatoa
{
   
    public static void main (String[] args)
    {
        Krakatoa telnet = new Krakatoa();
        telnet.getMeHookedUp();
    }

    public void getMeHookedUp()
    {
        boolean kingdomcome=true;

        while(kingdomcome)
        {
            Socket sock = null;

            try
            {
                System.out.println("Waiting for Server to Connect ...");
                sock = new Socket("192.168.81.146",23);
                System.out.println("Connection Established.");
            }
            catch(IOException nosock)
            {
                System.out.println("Doh. Server still out.");
                sock = null;
                System.gc();
                getMeHookedUp();
            }

            boolean sockup = true;

            while (sockup)
            {
                try
                {
                    sock.setKeepAlive(!sock.getKeepAlive());
                }
                catch(SocketException sockex)
                {
                    sockup=false;
                }

                try
                {
                    Thread.sleep(5000);
                }
                catch(InterruptedException dontbustinlikethat)
                {
                }
            }
        }
    }
}
=================================================

When I start it I receive the following text:

Waiting for Server to Connect ...
Connection Established.

Best regards,
  Sasha

P.S. My e-mail is adla bac att cg dot yu
I have tried to email you three times and failed. :(
OK I tried to email you from hotmail address. Check it out.
Avatar of adlabac

ASKER

I received the mail...

Best regards,
  Sasha
Its a good time for you to log on now iff you can ... I am extremely busy later on.
Avatar of adlabac

ASKER

I received the following error:

No server was online to accept your connection. Contact your system manager, or try again.

Maybe its my company's firewall. Let me try from other computer...

Best regards,
  Sasha
Can you ping my IP at least?
Avatar of adlabac

ASKER

Yes, I can ping you, but unfortunatelu I cannot pass through those ports... :(

Best regards,
  Sasha
>>, I found no way to detect when server disconnect me

Why should it btw?
Avatar of adlabac

ASKER

> >, I found no way to detect when server disconnect me

> Why should it btw?

Why?!? So I can finish the appllication/thread and/or to try to connect again.

Best regards,
  Sasha
The server disconnects you when you ask it to unless there's some sort of error/timeout. Are you familiar with the Telnet protocol? If not, i don't see how you can write the application.
CEHJ: are you ssaying then that it will not be helpful under the circumstances to try to detect the server disconn via the 'normal' methods (akin to above).?
adlabac:

So we are (or I at least am) running low on fuel now. I would like you to tell me (again even if you have done so already) *how* you know that you are not online to the server?
I think there are more fundamental issues to be addressed first here. The existing code, which is flawed, and the protocol are just two considerations.
>> The existing code, which is flawed ...

I wont dispute that - particularly as I haven't tested it, ;), but whilst adlabac has chance to get back and think about the fundamentals, can you tell me where you see the flaws, so that I can ponder that meanwhile?
Your comment > 09/18/2003 01:52AM PDT : lets go over that again.

If you have obtained a connection with my code (which it seems you have), then that code will also tell you when its not connected any more. Its the same stuff as Windows and Delphi are using - Windows Sockets.

So put this line:

System.out.println("You have just lost your connection.");

after the line

sockup=false;

It looks to me that you *think* you are disconnected, but you are not.
If the above never prints out, then you are still connected IMHO.
>>can you tell me where you see the flaws

For one thing, Telnet requires special streams and character encodings. You might stand some chance of doing this if you use the (undocumented) sun.net.TelnetInputStream and output classes.

A brief summary of the protocol at http://www.scit.wlv.ac.uk/~jphb/comms/telnet.html
Or use a ready-made implementation of this non-trivial (and almost obsolete) protocol:

http://www.mud.de/se/jta/
Well I was approaching this simply from the point that he wants to know if the connection is up or down. I dont want to get involved in telnet programming, but I would say that because it still runs over a socket of the same king that Java uses, all we need to do is establish whether that connection is viable or not.
SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
We've come full circle, I think you'd agree. Only adbalac doesnt seem to agree, which kinda defeats the purpose.

adbalac: do this for me - run my code with the new line in it as I gave you above, then when you've launched it, pull your modem card cable out of the PC.

Tell me what you get printed to your console then.
Avatar of adlabac

ASKER

Oh, man, will this ever end?!? If I only never asked this qustion...

First of all, I *never* claim something I don't know! Second, I have great experience in TCP/IP programming (including Telnet), only not in Java.

Krakatoa, I tried your code, corrected it and sent the correct version, so you can see where you made mistakes. At the begining it writes:

  Waiting for Server to Connect ...
  Connection Established.

And never writes "You have just lost your connection.".

How I know server disconnects me? Easy! One example - if I conect to the server it waits for username. If I send nothing for a minute it will disconnect me automaticaly! If I start krakatoa's program it will never say I lost the connection. Simple Windows' Telnet will close the window after one minute, as well as my Delphi application!

These days me and my coleaques searched the Internet and books to find a solution for this in Java and found many same questions and no one answer!

Please, in the future, try the code first, before sending any coments. Otherway, we are just waisting time.

Best regards,
  Sasha
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of adlabac

ASKER

You know what, I clearly see that this torture will never end until I give you the points and finish this discussion. I hope the points will wound the wonds caused by spending those thousands of dollars on me.

CEHJ, a few points for you, too, just in case.

Best regards,
  Sasha
No points is not the issue. Give them to CEHJ, I am not here for that.
Avatar of amnongg
amnongg

Hi adlabac

I'm having the exact same problem as you when I try do check for a socket disconnection.
did you find any solution for this problem ?

Thank you
Amnon
Avatar of adlabac

ASKER

No, and, unfortunatelly, it appears that there is no right solution in Java...

Best regards,
  Sasha