Link to home
Start Free TrialLog in
Avatar of richardsimnett
richardsimnett

asked on

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();
          }
    }
}

Avatar of richardsimnett
richardsimnett

ASKER

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
SOLUTION
Avatar of Tommy Braas
Tommy Braas
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
Please provide the stack trace from your OOM?
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
SOLUTION
Avatar of Mayank S
Mayank S
Flag of India 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
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.
Does the client code cose its connection to the server when it is done sending the maps?
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
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

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
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
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

are u still getting it?
 
>> 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.
objects,
yep... at the exact same place. Same exact error too.

Thanks,
Rick
If the client closes the connection, you will get the exception, of course....
>> 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.
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
>> 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:

https://www.experts-exchange.com/questions/21757720/Is-there-any-sample-online-for-socket-and-multi-thread.html#16084277
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

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
objects,
IT WORKS! Thanks a whole bunch, what made you think of that?

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

-Rick
>> 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 () ?
>> >> 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).
Just for the sake of curiosity, can you also try flush () instead of reset () and see if it works?