Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 917
  • Last Modified:

Sending a hashtable over a socket continued

Hello,
This is a continuation of a previous question (). I have written this code which is a thread that is spawned upon the successful connection of a serversocket. All it is supposed to do is collect the hashtable sent by the client, and count the # of hashtables recieved (this code is only used for proofing at the moment, once I have this figured out I will make it quite a bit more elegant). Anyways I have the following problems with it.

#1 - Why when I terminate the client feeding the hashtables does it not properly recognize the connection as broken and just keep spitting Exceptions?

#2 - Why does it throw a java outofmemory exception after receiving consistently 32768 hashtables?

Correct answers to these questions is worth 500 points. Code is below.

Thanks,
Rick

import java.net.*;
import java.io.*;
import java.util.*;

public class dataThread extends Thread {
    private Socket socket = null;

    public dataThread(Socket socket)
    {
          super();
          this.socket = socket;
    }

    public void run()
    {
          int count = 0;
          try
          {
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                
                while (socket.isClosed() == false)
                {      
                try
                {
                      Hashtable hs = (Hashtable) in.readObject();
                
                        //data was received
                      count++;
                            
                      System.out.println(count);
                
                }
                catch (IOException e)
                {
                      System.out.println("Error while reading hashtable.");
                    
                }
                catch (ClassNotFoundException cnfe)
                {
                      System.out.println("Error while reading hashtable. 2");
                }
                }
            }
            catch (IOException ie)
            {
            }
            
   
          //thread is done
          try
          {
              socket.close();
          } catch (IOException e)
          {
                e.printStackTrace();
          }
    }
}

0
richardsimnett
Asked:
richardsimnett
  • 12
  • 8
  • 5
  • +1
4 Solutions
 
richardsimnettAuthor Commented:
0
 
richardsimnettAuthor Commented:
Also, I have tried replacing:

 while (socket.isClosed() == false)

with

  while (socket.isConnected() == false)
 
to fix the connection break error, and it made no difference.

Thanks,
Rick
0
 
Tommy BraasCommented:
You can't trust socket.isConnected() for detecting connection state during a connection except immediately after connect to validate that a connection was established. socket.isClosed() keeps state whether the socket was closed after a call to socket.close().
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
Tommy BraasCommented:
Please provide the stack trace from your OOM?
0
 
richardsimnettAuthor Commented:
orangehead911,
Ok so if neither of those give me the actual socket connection state, how do I get it?

Stack Trace is on the way.

Thanks,
Rick
0
 
Mayank SAssociate Director - Product EngineeringCommented:
That's the trick - until you do any data-transfer, you cannot trust isConnected (). It stores the result of the last I/ O operation (read or write) - if it was successful, it will return a true otherwise a false. But if the connection borke after that I/ O, you can only come to know about it when you try to read or write again.

I would suggest that you send a "CLOSE" packet from the client so that the server closes the socket gracefully at its end, instead of waiting for an exception to be thrown and then displaying the error-message.
0
 
Tommy BraasCommented:
Only actual I/O can determine if a socket is connected.

Also, just like socket communication initiation is done in a certain sequence, so should socket termination.
0
 
Tommy BraasCommented:
Does the client code cose its connection to the server when it is done sending the maps?
0
 
richardsimnettAuthor Commented:
java.io.StreamCorruptedException
        at java.io.ObjectInputStream.readObject0(Unknown Source)
        at java.io.ObjectInputStream.readObject(Unknown Source)
        at dataThread.run(dataThread.java:25)
java.io.StreamCorruptedException
java.lang.OutOfMemoryError
0
 
richardsimnettAuthor Commented:
Orangehead911,
yes it does, however, that is not the issue I am concerned about. I am more concerned about actual network errors etc, taking the process out. The project is meant to transmit large amounts of data to remote facilities, obviously in between network conditions may be a factor, so I need to be able to tell when a connection is dropped, so that I can log the error, and attempt to reopen the connection from the client. For the server, I need it to detect a break so that the thread can terminate.

Thanks,
Rick

0
 
richardsimnettAuthor Commented:
mayankeagle,

that cant be true, if it was then my loop up there would terminate after throwing 1 exception (with isConnected as well) as the i/o event would trigger a false value when it throws an exception. This thing just loops forever throwing the exception. At this point I am assuming I have to rely on exceptions in order to tell if a connection is broken, and that doesnt seem very efficient to me.

Thanks,
Rick
0
 
objectsCommented:
you continue to try and read after a i/o error. once you get an error you need to end the thread.
you can do this by moving the loop *inside* the try/catch block
0
 
richardsimnettAuthor Commented:
objects,
hehe... your right! I totally overlooked the retartedness of that thread code. Heres the new code after your suggestion:

import java.net.*;
import java.io.*;
import java.util.*;

public class dataThread extends Thread {
    private Socket socket = null;

    public dataThread(Socket socket)
    {
          super();
          this.socket = socket;
    }

    public void run()
    {
          int count = 0;
          ObjectInputStream in;
          
               try
               {
                in = new ObjectInputStream(socket.getInputStream());
             
                while (socket.isClosed() == false)
              {      
                            Hashtable hs = (Hashtable) in.readObject();
                      
                            //data was received
                            //so feed it to PMTA
                            count++;
                            
                            System.out.println(count);
              }
                
          }
          catch (Exception e)
          {
                e.printStackTrace();
                e.getMessage();
          }      
            
          //thread is done
          try
          {
              socket.close();
          } catch (IOException e)
          {
                e.printStackTrace();
          }
    }
}

Any idea about how to correct the out of memory error?

Thanks,
Rick

0
 
objectsCommented:
are u still getting it?
 
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> that cant be true,

What can't be true?

>> if it was then my loop up there would terminate after throwing 1 exception (with isConnected as well)

isConnected () will not check for network connection - it will just return the status of the last I/O.

>> At this point I am assuming I have to rely on exceptions in order to tell if a connection is broken

Did you try the approach which I suggested? Sending a "CLOSE" packet so that the server gracefully closes it.

>> yes it does, however, that is not the issue I am concerned about

If you send just one hashtable from the client and close the connection, why do you loop again at the server, waiting for more hash-tables? The other hash-tables will come in the other threads, right? Just wait for the hash-table to come once and then close the socket.

You probably get out-of-memory error because you create too many threads and keep them alive when they are not required. You should dispose of them when the clients are disconnected.
0
 
richardsimnettAuthor Commented:
objects,
yep... at the exact same place. Same exact error too.

Thanks,
Rick
0
 
Mayank SAssociate Director - Product EngineeringCommented:
If the client closes the connection, you will get the exception, of course....
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> You should dispose of them when the clients are disconnected.

By exiting out of the loop. In fact, if you read only one hash-table per client, you don't even need a loop.
0
 
richardsimnettAuthor Commented:
mayankeagle,
>>What can't be true?
>>isConnected () will not check for network connection - it will just return the status of the last I/O.

Sorry I have to take that back after objects pointed out putting the loop in the try, the way it was originally structured that wouldnt have worked.

>>Did you try the approach which I suggested? Sending a "CLOSE" packet so that the server gracefully closes it.

The code will use a CLOSE command as the protocol, however, at the moment I am more concerned about ironing out all the exception handling. Considering this will work over the internet (not a local network) I have to compensate, and correct errors that may occur. Such as dropped connections, timeout errors, etc.

>>If you send just one hashtable from the client and close the connection, why do you loop again at the server, waiting for more hash-tables? The other hash->>tables will come in the other threads, right? Just wait for the hash-table to come once and then close the socket.

The intent is that it will loop as designed above. It should receive limitless #'s of hashtables until either A) the datasend session is complete (as designated by the to-be-designed protocol) or B) a network error occurs.

>>You probably get out-of-memory error because you create too many threads and keep them alive when they are not required. You should dispose of them when >>the clients are disconnected.

Also this is a single thread running. I open 1 connection and run a single thread. There aren't multiples, nor is this in the spec of the project.

Thanks,
Rick
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> or B) a network error occurs.

You should put the while () inside the try block, then, as suggested.

>> The code will use a CLOSE command as the protocol,

Is it implemented? I don't see it.

>> Also this is a single thread running. I open 1 connection and run a single thread

For multiple clients, you should use multiple dedicated threads at the server. Refer to this:

http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_21757720.html#16084277
0
 
richardsimnettAuthor Commented:
mayankeagle,

>>You should put the while () inside the try block, then, as suggested.

The while has been put in the try block, and the code has been reworked a bit (see the post to objects above).

>>Is it implemented? I don't see it.

The actual transfer protocol hasnt been designed yet. I just know that it will be based on hashtables in and text out. After each hashtable is processed I am going to have it return an OK response with some diagnostic information. The client will send a hashtable with the embedded command CLOSE as the final hashtable, which when implemented the thread will catch and terminate.
As I said before at this point I am simply trying to eliminate all of the exception issues that can arise with connections over the internet. I will concentrate on the protocol after this.

>>For multiple clients, you should use multiple dedicated threads at the server.

No the server will only receive a single connection from a single ip, and will only have a single thread serving the server socket. It will never need to support multiple worker threads for the server socket.

At the moment the only issue I still have is the Out Of Memory Issue. Which occurs exactly 37635 hashtables after the transfer begins. It occurs when I try to read the object after hashtable #37635 (the stack trace says java.io.StreamCorruptedException... see above).

Thanks,
Rick

0
 
objectsCommented:
On the sending side try calling reset() on the OOS after sending each Hashtable.
0
 
richardsimnettAuthor Commented:
objects,
IT WORKS! Thanks a whole bunch, what made you think of that?

Thanks,
Rick
0
 
objectsCommented:
object streams use a cache, and reset() clears it.
0
 
richardsimnettAuthor Commented:
I totally overlooked that. Thanks for the help.

-Rick
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> It will never need to support multiple worker threads for the server socket.


>> On the sending side try calling reset() on the OOS after sending each Hashtable

You mean flush () ?
0
 
Mayank SAssociate Director - Product EngineeringCommented:
>> >> It will never need to support multiple worker threads for the server socket.

Sorry I forgot to answer to that. Well, see the link which I posted above for a multi-threaded server. I didn't mean that you need multiple threads for the server socket. The server socket will be in one thread (the main-thread) and whenever it receives a client connection, it will spawn a new thread like your "dataThread" class, and hand over the socket to it (I guess, unknowingly, this is what you do anyway). That way the server's main-thread can also go back to the job of listening and it will serve two purposes - a) multiple clients can be handled if required, it anyway supports 1 client also, b) if the current client gets disconnected, it can connect again and it will be handled as another client by another thread (the previous thread will come out of the while () loop and the run () method, and die).
0
 
Mayank SAssociate Director - Product EngineeringCommented:
Just for the sake of curiosity, can you also try flush () instead of reset () and see if it works?
0
 
Tommy BraasCommented:
;-D
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 12
  • 8
  • 5
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now