Unexpected timeout error

Hey all...

I have a client and a server application. What I'm trying to do here, is have one socket write a string to the other; while, of course, the other reads that string....

Okay, both of the two applications use these methods to read and write data, to and from a socket:

            // Write
            protected void write( Socket sock, String str )
            {
                try
                {
                    if ( sock == null )
                        throw new Exception();
                   
                    if ( wr == null )
                        wr = new BufferedWriter( new OutputStreamWriter( sock.getOutputStream() ) );
                    wr.write( str );
                    wr.flush();
                } catch ( Exception e )
                {
                    setStatus( "Socket exception has occured." );
                    e.printStackTrace( System.out );
                }
            }



        // Read
        protected String read( Socket sock )
        {
            try
            {
                if ( sock == null )
                    throw new Exception();
               
                if ( rd == null )
                {
                    rd = new BufferedReader( new InputStreamReader( sock.getInputStream() ) );
                }
                String str;
                String ret = "";
                while ( (str = rd.readLine()) != null )
                {
                    ret += str;
                }
               
                return ret;
            } catch ( Exception e )
            {
                setStatus( "Socket exception has occured." );
                e.printStackTrace( System.out );
            }
           
            return null;
        }


Now, here's what is suppose to happen:

...
CLIENT writes "password:2" to SERVER
SERVER reads "password:2" from CLIENT
SERVER writes "g" to CLIENT
CLIENT reads "g" from SERVER
...

However, it only completes stage one with no problems (CLIENT writes "password:2" to SERVER); the Client writes the String, then starts reading from the socket (well; blocking until it gets some data). However, the server isn't reading anything.. It all comes to a hault, when the Client throws a 20 second timeout exception. So, I'm guessing there's something wrong with my   read(Socket)   method?

Does it look dodgey at all? lol.

Regards;
>> IM
LVL 25
InteractiveMindAsked:
Who is Participating?
 
Mayank SAssociate Director - Product EngineeringCommented:
Why are you calling createServer () at both the places, even at the client? I would write a client/ server this way:

public class Server
{
  public static void main ( String[] args )
    throws Exception
  {
    ServerSocket ss = new ServerSocket ( 2725 ) ;
    while ( true )
    {
      new ServerThread ( ss.accept () ) ;
    }
  }
}

class ServerThread extends Thread
{
  private Socket s ;
  private BufferedReader br ;
  private PrintWriter pw ;

  public ServerThread ( Socket s )
    throws Exception
  {
    this.s = s ;
    br = new BufferedReader ( new InputStreamReader ( s.getInputStream () ) ) ;
    pw = new PrintWriter ( new PrintWriter ( s.getOutputStream (), true ) ) ;
    start () ;
  }    
 
  public void run ()
  {
    while ( true )
    {
      // read messages from the client using br.readLine () and process them
      // send messages to the client using pw.println ()
    }
  }
}

The client would just open a socket using:

Socket s = new Socket ( "IP of server", 2725 ) ;
BufferedReader br = .... ; // similar to above
PrintWriter pw = ....

Use pw.println () to send messages to the server and br.readLine () to read messages
0
 
CajunBillCommented:
So I'm guessing that Server hangs on the rd.readline, is that correct?
Perhaps it is because Client is not writing an end of line??

HTH
Bill
0
 
objectsCommented:
Try using a PrintWriter instead of a BufferedWriter
0
Cloud Class® Course: Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

 
Mayank SAssociate Director - Product EngineeringCommented:
I would use a PrintWriter too, with flush on new-line set to true:

PrintWriter pw = new PrintWriter ( sock.getOutputStream (), true ) ;
pw.println ( str ) ;
0
 
InteractiveMindAuthor Commented:
Thanks all.
I've changed the write() method to this:

        protected void write( Socket sock, String str )
        {
            try
            {
                if ( sock == null )
                    throw new Exception();
               
                if ( wr == null )
                    wr = new PrintWriter( sock.getOutputStream(), true );
                wr.println( str );
            } catch ( Exception e )
            {
                setStatus( "Socket exception has occured." );
                e.printStackTrace( System.out );
            }
        }

but I'm having the same problem (timeout exception).. Which, CajunBill was correct about: is occuring on the Clients' rd.readLine() call.

Perhaps I need to change the read() method also??

Regards;
0
 
Mayank SAssociate Director - Product EngineeringCommented:
At the client, are you calling the setSoTimeout () method on the socket anywhere?
0
 
Mayank SAssociate Director - Product EngineeringCommented:
By the way, how many times are you calling the write () and read () methods? You should not create a new PrintWriter and BufferedReader everytime you call those methods. Instead, you should create them once (maybe in the constructor) and maintain them as data-members of the class and re-use the same instances everytime.
0
 
InteractiveMindAuthor Commented:
I've temporarily removed the setSoTimeout() calls. I've initialized the PrintWriter and BufferedReader from outside the read() and write() methods, although I have so far, only called each one once.

Still no change... I've set the server to read the String, then output it, like so:

String data = read();
System.out.println( data );

But, it gets stuck on the read(); call.

This is really strange. Agreed? lol.. I'm not the greatest programmer obviously, so it must be something I've done (or, something I've not done).. But I just can't make sense of it..
I'm only connecting to localhost here, and it's connecting fine, but no data is able to get transferred: what is the likelyhood of my firewall allowing the connections, but blocking any data transfer?? (I'm sure; and kind of hoping very low, but...?).

Cheers.
0
 
CajunBillCommented:
IM, hope you don't mind if I ask for a little clarification here.

First, how do Client and Server share the socket variable (in other words, how sure are you that they are actually talking to each other, instead of talkking to the ether?  )
Also, please let us know if the situation is as follows:

- Client runs first, (not that this should be necessary, but just to clarify since problems are happening right now)
- Client prints to scket, then hangs on readLine()
- Server runs second, hangs on readLine()
- Confirm to us that you have sprinkled debug statements in the code or have some other way to tell you how far it is getting before hanging

CajunBill
PS - since both endpoints are in the same machine right now, the firewall should not be a problem.  But is it an external firewall or is it a program that runs on the server, such as ZoneAlarm?
0
 
InteractiveMindAuthor Commented:
Firstly, it's Sygate Personal Firewall.. However, I just thought to check the logs, and I've also added a rule, to allow all local traffic on port 9090 (the port that I'm using for this).. So, I now doubt that the firewall is doing anything - but it would be the biggest pain if it is, because my machine is the ICS host, so I can't afford to turn off the firewall. :(

Anyway, back to it:
Yes, I have a way of finding out where exactly it is: my GUI's JLabel 'status' component changes, to tell me what it's done so far, e.g. for the Server:

Waiting for client connection . . .
Client has connected.
Creating secondary connection . . .
Secondary connection created.
Authenticating client . . .

That's where it gets up to.. this is actually the point where the server should be reading for the password and a few other configs from the client.
The client would then write the password, etc, to the server, and then start to read(), and block until any data arrives (but a timeout exception of 20 seconds keeps occuring).

I've also set it, so that once the server recieves any data from the client, then it outputs it to the command line. But, obviously, it doesn't ever do this, because it doesn't get past the read() statement.

Surely there's something wrong with my read() method?!? :o\

Best Regards;
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> I've temporarily removed the setSoTimeout() calls.

Better not to set it :)

>> I've initialized the PrintWriter and BufferedReader from outside the read() and write() methods

Can you post the updated code (where you initialize them, and how you have defined the read () and write () methods)?
0
 
CajunBillCommented:
I second mayaneagle's request for more information.
What I hope you will provide is the code that you use to set up the sockets.

My suspicion at this point is that the problem is in the subtle details of the sockets, not in the read routine itself.
CajunBill
0
 
InteractiveMindAuthor Commented:
Sure.
I'm actually making two connections between the Server and Client, both on different ports; lol, I'm sure you're thinking that they're probably reading and writing from different ports, but I've checked this, and I'm confident that this is not the case! :) lol

Okay, I'm doing the following (excluding everything unecessary):


// Server Application

private   Socket               sock1              = null;      // Class instances
private   Socket               sock2              = null;      //
private   PrintWriter         wr                  = null;      //
private   BufferedReader  rd                   = null;      //
...
sock1 = createServer( port, 0 );
sock2 = connectTo( sock1.getInetAddress().getHostName(), port+1 );
wr = new PrintWriter( sock1.getOutputStream(), true );
rd = new BufferedReader( new InputStreamReader( sock1.getInputStream() ) );
String auth = read();             // It doesn't pass here
System.out.println( auth );
write( "g" );
...

// Client Application

private   Socket               sock1              = null;      // Class instances
private   Socket               sock2              = null;      //
private   PrintWriter         wr                  = null;      //
private   BufferedReader  rd                   = null;      //
...
String server = "servername";      // this string is actually retrieved from a JTextField
sock1 = connectTo( server, port );
sock2 = createServer( port+1, timeout );    // timeout is currently 0
wr = new PrintWriter( sock1.getOutputStream(), true );
rd = new BufferedReader( new InputStreamReader( sock1.getInputStream() ) );
...
write( password + ":" + res );    // 'res' is an integer
String response = read();          // It doesn't pass here
System.out.println( response );



Then, for the method calls that I've made in those codes, here they are:


private Socket createServer( int port, int timeout )
        {
            try
            {
                ServerSocket srv = new ServerSocket( port );
                if ( timeout > 0 )
                    srv.setSoTimeout( timeout * 1000 );
               
                return srv.accept();
            } catch ( InterruptedIOException ioe )
            {
                setStatus( "Secondary Connection Timeout error has occured." );
                ioe.printStackTrace( System.out );
                error( "Timeout error", "The server failed to respond with a Secondary connection within " + timeout + " seconds." );
                System.exit( -1 );
            } catch ( Exception e )
            {
                setStatus( "Secondary Connection Error has occured." );
                e.printStackTrace( System.out );
                error( "Connection error", "An error occured while creating a Server Socket on port " + port );
                System.exit( -1 );
            }
            return null;
        }
       
        private Socket connectTo( String server, int port )
        {
            try
            {
                return new Socket( InetAddress.getByName( server ), port );
            } catch ( Exception e )
            {
                setStatus( "Connection Error has occured." );
                e.printStackTrace( System.out );
                error( "Connection error", "An error occured while attempting to connect to server." );
                System.exit( -1 );
            }
            return null;
        }


And you've seen the read() and write() methods (previously).

lol.. I would post all of my code, but there's a *lot*, and at least to anyone else, it truly is spaghetti! ;-P

Thanks very much for sticking with this guys, I really appreciate it. Regards;
0
 
CajunBillCommented:
Are you using MX4J ?
0
 
InteractiveMindAuthor Commented:
> Are you using MX4J ?
I don't know what that is, so that'll be a "no" ;)
0
 
CajunBillCommented:
OK, IM,
Just quickly without running the code myself, it looks like one or the other of Client or Server must be catching an exception and returning a null.
Let's say you run Server first - then when it tries to connect to the port from the client, it cannot, since it is not created yet.
If you run Client first, then it cannot connect to the server port, because that port is not created yet.
It looks like a form of "race condition" to me.
You can fix that by having Server start first, then have server kick off the Client process, then wait a few seconds or wait for some flag or other indication from Client, before trying to connect to the client's port.
HTH
Bill
0
 
InteractiveMindAuthor Commented:
Thanks all.
0
 
objectsCommented:
no worries :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.