Link to home
Start Free TrialLog in
Avatar of Venki533
Venki533

asked on

Socket Events in Java

Hi,

Here is what I'm trying to acheive in terms of retrieving data from sockets connections to my server.

The server can accept multiple socket connections. And as soon as it gets a socket connection it hands it off to a ProcessSocket  class which extends Thread.

while (LISTENING)
        {
        new ProcessSocket(serverSocket.accept()).start();
        }

in the ProcessSocket class I basically do the following

DataInputStream din = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
byte mesg [] = new byte[];
while(true)
   {
     if(din.read()>0)
     {
         din.readFully(mesg);
     }
     else
     {
          Thread.sleep(500);
      }
    }

I feel this is a bad way to monitor a socket for any incoming data. Is there an way I can look for events on a socket when there is data with a third party API maybe? Can someone suggest a better way to do this in Java?

And also what is the limit on how many incoming socket connections a JVM allows to an application?

Any help is appreciated.

Venkatesh.
Avatar of Mick Barry
Mick Barry
Flag of Australia image

>      if(din.read()>0)

that should be calling available() not read()

     if(din.available()>0)

but that could still block (I assume you are trying to avoid blocking) if there isn't enough data to fill buf
Avatar of Venki533
Venki533

ASKER

I did'nt see a  method available() in the DataInputStream class in Java 1.4 api. Blocking would be ideal here. I could'nt find a Class that has methods that would block on a stream read operation until there are bytes. Any ideas if there any classes like that? I could find them in 1.4 api either.

most of the I/O methods will block until data is available, you could use something like this:

DataInputStream din = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
byte mesg [] = new byte[256];
int n = 0;
while ((n=din.read(mesg))>=0)
{
   // process the n bytes read into mesg buffer
}

hi venki,

>>And also what is the limit on how many incoming socket connections a JVM allows to an application?

I dont think there is any limitation, it depends only on the max socket connections set in the ServerSocket.

>>  Can someone suggest a better way to do this in Java?
In  C++, specially for this purpose, there are functions like poll and select [ which will notify you after input comes].
I dont know exact functionality in java. But you could use JNI to use that functionality in C++.

Hope this helps
Hi Objects,
   The method read() seems to return a -1 when there is no data on the input stream and runs in a continuous loop :/

Also is there a way to detect socket disconnect on the client side without depending on exceptions?

The following is my code. Can you confirm if I'm doing something wrong?

------------------------------------------------------------------------------------
public class SocketHandler implements Runnable {
      private Socket sock=null;
      private DataInputStream din = null;
      private String message=null;
      public SocketHandler(Socket socket){
            this.sock=socket;
      }
      public void run() {
            try {
                        din =new DataInputStream( new BufferedInputStream(sock.getInputStream()));
                  processSocketStream(bin);
            } catch (IOException e) {
                  e.printStackTrace();
                  cleanup();
            }
      }
      
      private void processSocketStream(DataInputStream dins) throws IOException{
            ReadData rdata = new ReadData(dins);
            while(true){
                  System.out.println("SocketHandler::processSocket:: message = "+rdata.message());
            }
      }
      
      private void cleanup(){
         try {
            if(sock!=null)      {
                  sock.close();
            }
                if(din!=null){
                    din.close();
                }
          } catch (IOException e) {
                  e.printStackTrace();
         }
      }

-----------------------------------
public class ReadData {
      private DataInputStream din = null;
      public ReadData(DataInputStream dins){
            this.din = dins;
      }
      public String message() throws IOException
      {
            byte [] message = new byte[20];
            int n=0;
            n=din.read(message);
            System.out.println("ReadData::message():: bytesRead = "+n);
            return new String(message);
      }
}

--------------------------------------------
Durga Prasad thank you for the help. But I do not want to add the complexity of JNI into my code right now, as that involves a learning curve. And I heard the max number of socket connections is dependent on the OS?

I increased the points to 600 for the extra questions i'm posing.

Thank You,

Venkatesh.
I guess the max points that can be awarded is 500. lol. Sorry about that.

messed up again
> The method read() seems to return a -1

it returns -1 on eof

> Also is there a way to detect socket disconnect on the client side without depending on exceptions?

I don't think so

> public String message() throws IOException

What is your intention for this message?  What is actually being sent to it?

it returns -1 on eof
when bytes are written to the stream by the client, how can i just make the read() method read all of it and just wait for the next set of bytes then?

What is your intention for this message?  What is actually being sent to it?
Message could be anything. Once i get a string back from the socket input stream, i'm gonna hand it off to a message handler and process it based on its header field values.

So  what I want  to achieve is to have a method read data on the input stream every time something new shows up until the client closes the socket connection.

 
If you are passing strings as messages then a BufferedReader may be more applicable for reading the messages.
How are the message being written on the sending end.
thanx for all your help. I'm sick of not having events to know that there is data to read on the socket's stream. I can not believe no one has run into this problem before using Java. All I wanted to do was have a reader sit there until a new message appears on the stream,  just like serverSocket.accept() sits there until a new socket connection requests arrives.


while (true){
    read(byte); // block damnit, I dont need the lame -1
}

without the while  loop going into a continuous loop taking up cpu, and without having to use a Thread.sleep();

Venkatesh.


ASKER CERTIFIED 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 dont think that while loop will work. It will miss the first line of the message. Am I wrong thinking that?    
that loop will read each line (terminated by a newline), it won't lose the first line