Hello,

I'm making an application that supports sending text/files. It will use a server and 2+ clients. The clients won't communicate directly with each other, their messages will be forwarded by the server.

My problem is this: in C++, after starting a client, I'd have 1 thread stuck on RECEIVE (recv), for handling messages any time they'd come.

How do I do this in Java? thanks.

Socket socket = new Socket(host.getHostName(), 7777);

            //
            // Send a message to the client application
            //
            ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
            oos.writeObject("Hello There");

            //
            // Read and display the response message sent by server application
            //
            ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
            String message = (String) ois.readObject();
            System.out.println("Client: Message: " + message);

Normally, as each client connects, you start a new Thread to handle I/O from that one client. You end up with one thread waiting for new connections, plus 1 thread per client waiting for I/O (plus threads for GUI etc).

Normally, as each client connects, you start a new Thread to handle I/O from that one client. You end up with one thread waiting for new connections

I have that part figured out - the socket.accept() causes the program to wait until a connection is established.

while (true) {
          
                Socket socket = server.accept();
        //bla bla
        }

, plus 1 thread per client waiting for I/O (plus threads for GUI etc).

That's what I need. How do I use a thread that blocks the program until data is received through the Socket object?

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            
            String message=in.readLine(); 
            
            System.out.println("Client: received message: " + message);

Thanks for your time.

According to http://www.javaworld.com/jw-09-1999/jw-09-timeout.html?page=2 :

Let's take a look at how this works. A new method, setSoTimeout ( int ) has been added to the following socket classes: 
- java.net.Socket
- java.net.DatagramSocket
- java.net.ServerSocket

This method allows us to specify a maximum timeout length, in milliseconds, that the following network operations will block:

ServerSocket.accept()
SocketInputStream.read()
DatagramSocket.receive()

So I've tried this:

InputStreamReader isr = new InputStreamReader(socket.getInputStream());

socket.setSoTimeout(10000);

char[] buffer=null;

isr.read(buffer); //still won't wait 10sec

System.out.println("Client: Message: " + buffer.toString());
public int read(char[] cbuf)
         throws IOException
Reads characters into an array. This method will block until some input is available, an I/O error occurs, or the end of the stream is reached.

It goes like this (in outline - details all omitted)...

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
  String message=in.readLine(); 
  System.out.println("Client: received message: " + message);
}

That all goes in the run() method for a class that extends Thread (eg "ClientHandler").

while (true) {
  Socket socket = server.accept();
  new ClientHandler(socket).start();
}

It goes like this (in outline - details all omitted)...

BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while (true) {
  String message=in.readLine();  // I need this to wait until something's received
  System.out.println("Client: received message: " + message);
}

That's what I have been trying. It doesn't wait/hang until something is actually received, it just prints out:

Client: received message: null
Client: received message: null
...
Client: received message: null
Client: received message: null

Edited 5 Years Ago by Buffalo101: n/a

That's weird. Can you post more of the code? Are yo getting any Exceptions thrown?

ps Are you continuing to try to read after the client has closed the socket or stream from it's end?

Edited 5 Years Ago by JamesCherrill: ps

I eventually fixed it. Don't exactly know what I was doing wrong, but it's working now.

One more question: how do I know when the socket has been closed by the server, so I know how to stop the ClientHandler (the thread that listens for received messages) ?

InetAddress host = InetAddress.getLocalHost();
            Socket socket = new Socket(host.getHostName(), 7777);

            new ClientHandler(socket);
public class ClientHandler implements Runnable {
	private Socket socket;
	
	public ClientHandler(Socket socket){
		this.socket=socket;
		
		Thread t=new Thread(this);
		t.start();
				
	}
	
	@Override
	public void run() {
		
		ObjectInputStream ois = null;
															   try {
		ois = new ObjectInputStream(socket.getInputStream());  }catch (IOException e1){e1.printStackTrace();}
		String message = null;
		
		System.out.println("listening thread. waiting for a message from the server");
		
	        try
	        {
	               	while(true){         //I need to prevent this from running after the socket's been closed
		            message = (String) ois.readObject();
		            System.out.println("client> message: " + message);
		            System.out.println("Waiting for another server message");
	        	}
	        } catch (IOException e) {
	            e.printStackTrace();
	        } catch (ClassNotFoundException e) {
	            e.printStackTrace();
	        }				

		}
		
		
		
		
		
	}

As far as I remember (not at desk now) when the Socket connection closes the read throws an Exception, so you just have to handle that tidily. It's common practice to have a "disconnecting now" messsage that either end can send to the other so the receiving end can exit its read loop and close without throwing any Exceptions

Thanks for the suggestions, JamesCherrill.

I'm beginning to doubt my choice of Java over c/c++ for this project. :)


LE:

ClientApplication:
                       new ClientHandler(socket);
                       [...]
                       socket.close(); // this line causes an exception to be thrown:
ClientHandlerThread:
	        	while(true){       
	        	    
		            message = (String) ois.readObject();  // exception thrown from this line
		            System.out.println("client> message: " + message);
		            System.out.println("Waiting for another server message");
		            
	        	}

So if I'm in my main application and I want to exit, how can I stop the handler thread from running? or what should I be doing? thank you!

Edited 5 Years Ago by Buffalo101: n/a

Catching the Exceptions when the socket closes (for whatever reason) is an ordinary thing to do. If the loop is inside the try clause then the catch will be outside the loop, thus exiting it. After the catch clause execution falls thru to the end of the run() method, and the Thread terminates normally.
It's often hard for people to make the mental change of gear between c++ and Java. I'm not going to argue here that either is better, but they do have different idioms and assumptions to catch out the unwary convert.

This question has already been answered. Start a new discussion instead.