Link to home
Start Free TrialLog in
Avatar of InteractiveMind
InteractiveMindFlag for United Kingdom of Great Britain and Northern Ireland

asked on

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
Avatar of CajunBill
CajunBill

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
SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia 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
I would use a PrintWriter too, with flush on new-line set to true:

PrintWriter pw = new PrintWriter ( sock.getOutputStream (), true ) ;
pw.println ( str ) ;
Avatar of InteractiveMind

ASKER

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;
At the client, are you calling the setSoTimeout () method on the socket anywhere?
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.
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.
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?
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;
>> 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)?
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
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;
Are you using MX4J ?
> Are you using MX4J ?
I don't know what that is, so that'll be a "no" ;)
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
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
Thanks all.
no worries :)