Java Socket client hangs (blocks) when reading from server

Given the attached server and client code:  in ClientWorker.java, if I uncomment line21:  this.readFromSocket(), the client locks up and will not read.  It acts as though the client is blocking.  It has been a long time since I have tried to write Java sockets.  I was hoping I was doing something stupid and someone could help point that out.  What is causing this lock-up or blocking?
/*Socket Server Thread*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientWorker implements Runnable {
	private Socket socket;

	public ClientWorker(Socket socket) {
		this.socket = socket;
	}

	/**
	 * Run method of Runnable interface, does all the work.
	 */
	public void run() {
		try {
			//this.readFromSocket();
			this.writeToSocket();
		} catch (Throwable t) {
			t.printStackTrace();
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private void readFromSocket() throws Throwable {
		BufferedReader in = null;
		String[] data = null;

		// Read data from socket
		in = new BufferedReader(new InputStreamReader(this.socket
				.getInputStream()));

		StringBuilder builder = new StringBuilder();
		String line = null;
		while ((line = in.readLine()) != null) {
			builder.append(line);
		}

		System.out.println(builder);
		data = builder.toString().split("::");
		for (String string : data) {
			System.out.println(string);
		}
	}

	private void writeToSocket() throws Throwable {
		PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true);
		out.write("READ_ME");
		out.flush();
		System.out.println("WROTE");
	}
}

/*Socket Client*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

public class SocketClient {
	private static Socket socket;

	public static void main(String[] args) throws Throwable {
		socket = new Socket(InetAddress.getLocalHost().getCanonicalHostName(),
				8080);

		write();
		read();

		closeConnections();
	}

	private static void write() throws Throwable {
		PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
		out.write("INVOICE::QUOTATION");
		System.out.println("WROTE");
	}

	private static void read() throws Throwable {

		BufferedReader in = null;
		in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

		System.out.println("READING");
		String line = null;
		StringBuilder builder = new StringBuilder();
		while ((line = in.readLine()) != null) {
			System.out.println("READING_LINE");
			builder.append(line);
		}
		System.out.println("RETURNED=" + builder);
	}

	private static void closeConnections() throws IOException {
		socket.close();
		socket = null;
	}
}

Open in new window

jimmyraywvAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
>> What is causing this lock-up or blocking?

Blocking will occur if there' s nothing yet ready to be read. Make sure you're only attempting to read when you know something's being written
0
Mick BarryJava DeveloperCommented:
>            out.write(

use println() instead of write
0
kurian2z5Commented:
When using read() the it will block until there is incoming data on the socket.

You can use socket.setSoTimeout(milliseconds). It will block and if no data is received within the timeout, it will throw SocketTimeoutException and you can continue excecuting remaining code.
0
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

mukundha_expertCommented:
>> What is causing this lock-up or blocking?
firstly you need ensure CEHJ's comment, if thats correct then may be this reason

readLine() expects a "\r\n" at the end to recognize a line,

hence you need to use println() as suggested by objects.


0
CEHJCommented:
>>readLine() expects a "\r\n" at the end to recognize a line,

Actually that's not the case. readLine will read whatever's in the buffer, irrespective of linefeed issues
0
mukundha_expertCommented:
but it will return only after a CR or LF or both or EOF(in which case returns null) right?
0
CEHJCommented:
In this case, EOF would be end of buffer and it would return, as i said, what's in the buffer. You should be able to verify that by reading a file with no CR/LF anywhere
0
mukundha_expertCommented:
oh.. yes.. in this case this is true. thank you.
0
jimmyraywvAuthor Commented:
Even though my testing did not indicate the need, I changed my write to println whether i am writing to the socket from the client or the server.  However, I get the same results.  If I try to read from the inbound socket, it blocks and I can never finish the read on the server and get my results from the server to the client.  The client is blocking and I still have not figured out why.
0
CEHJCommented:
>>I changed my write to println whether i am writing to the socket from the client or the server.

Yes, that will be a good idea although is probably not much to do with your problem.

Please post the server code if you can. Is it publicly accessible?
0
jimmyraywvAuthor Commented:
I added logic to the ClientWorker and the SocketClient to check to see if the input BufferedReader was ready().  It seems that if I try to read from both sides, BufferedReader is not ready on the second read.  Any ideas?
0
jimmyraywvAuthor Commented:
Here is the code...as of now.
public class ServerStarter {
	private static int PORT = 8080;
	private static int MAX_CONNECTIONS = 10;
	private static int NUMBER_XACTIONS = 100;

	public static void main(String[] args) {
		try {
			if (args.length >= 3) {
				try {
					PORT = Integer.valueOf(args[0]).intValue();
					MAX_CONNECTIONS = Integer.valueOf(args[1]).intValue();
					NUMBER_XACTIONS = Integer.valueOf(args[2]).intValue();
				} catch (Exception ignore) {
					// Ignore, keep default values
					System.err
							.println("WARNING::Server started with default settings.");
				}
			}

			System.out.println("Starting Server::PORT=" + PORT
					+ ", MAX_CONNECTIONS=" + MAX_CONNECTIONS
					+ ", NUMBER_XACTIONS=" + NUMBER_XACTIONS);

			// Start thread pool server
			Server server = new Server(PORT, MAX_CONNECTIONS, NUMBER_XACTIONS);
			new Thread(server).start();
		} catch (Throwable t) {
			System.out.println(t.getMessage());
			t.printStackTrace();
		}
	}
}

import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.om.tax.util.SimpleConsoleLogger;

public class Server implements Runnable {
	SimpleConsoleLogger logger = null;
	private boolean shutdown;
	private int port;
	private ExecutorService pool;

	/**
	 * Constructor
	 * 
	 * @param port
	 * @param size
	 * @param times
	 */
	public Server(int port, int size, int times) {
		// Port
		this.port = port;
		// need to match fixed pull size to ServerManager/ServiceContainer count
		this.pool = Executors.newFixedThreadPool(size);

	}

	/**
	 * Runnable run method, does all the work by listening on socket port.
	 */
	public void run() {
		try {
			// Get Logger instance
			logger = SimpleConsoleLogger.getInstance();

			// Get instance of ServiceManager
			// ServiceManager.getInstance();

			// Listen for socket connections
			this.listen();

		} catch (Throwable t) {
			t.printStackTrace();
		} finally {
			this.pool.shutdown();
		}
	}

	/**
	 * Listens for client connections over a socket. A thread is created for
	 * each connection.
	 */
	public void listen() {
		try {
			ServerSocket serverSocket = new ServerSocket(this.port);
			serverSocket.setSoTimeout(0);

			while (shutdown == false) {
				Socket socket = serverSocket.accept();
				ClientWorker worker = new ClientWorker(socket);
				this.pool.execute(worker);
			}
		} catch (Throwable t) {
			t.printStackTrace();
		}
	}

	/**
	 * Getter
	 * 
	 * @return
	 */
	private synchronized boolean isShutdown() {
		return this.shutdown;
	}

	/**
	 * Stops thread pool server.
	 */
	public synchronized void setShutdown() {
		this.shutdown = true;
	}

}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class ClientWorker implements Runnable {
	private Socket socket;

	public ClientWorker(Socket socket) {
		this.socket = socket;
	}

	/**
	 * Run method of Runnable interface, does all the work.
	 */
	public void run() {
		try {
			this.readFromSocket();
			this.writeToSocket();
		} catch (Throwable t) {
			t.printStackTrace();
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private void readFromSocket() throws Throwable {
		BufferedReader in = null;
		String[] data = null;

		// Read data from socket
		in = new BufferedReader(new InputStreamReader(this.socket
				.getInputStream()));

		StringBuilder builder = new StringBuilder();
		String line = null;
		if (in.ready()) {
			while ((line = in.readLine()) != null) {
				builder.append(line);
			}

			System.out.println(builder);
			data = builder.toString().split("::");
			for (String string : data) {
				System.out.println(string);
			}
		}

	}

	private void writeToSocket() throws Throwable {
		PrintWriter out = new PrintWriter(this.socket.getOutputStream(), true);
		out.println("READ_ME");
		System.out.println("WROTE");
	}
}

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

public class SocketClient {
	private static Socket socket;

	public static void main(String[] args) throws Throwable {
		socket = new Socket(InetAddress.getLocalHost().getCanonicalHostName(),
				8080);

		write();
		read();

		closeConnections();
	}

	private static void write() throws Throwable {
		PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
		out.println("INVOICE::QUOTATION");
		System.out.println("WROTE");
	}

	private static void read() throws Throwable {

		BufferedReader in = null;
		in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

		System.out.println("READING");
		String line = null;
		StringBuilder builder = new StringBuilder();
		while (!in.ready()) {
			System.out.println("NOT_READY");
			Thread.sleep(500);
		}
		while ((line = in.readLine()) != null) {
			System.out.println("READING_LINE");
			builder.append(line);
		}
		System.out.println("RETURNED=" + builder);
	}

	private static void closeConnections() throws IOException {
		socket.close();
		socket = null;
	}
}

Open in new window

0
CEHJCommented:
The server expects the client to write first. *It* will then block waiting for more input
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Mick BarryJava DeveloperCommented:
> Even though my testing did not indicate the need

it is needed, readLine() reads until eol. you weren't writing one.

>                   while ((line = in.readLine()) != null) {

readFromSocket() will never return as readLine() will not return null until eof is reached. Thats not going to happen until you close the stream

You either need seperate threads reading and writing to the socket.
Or define a protocol for the server and client to follow. eg. client sends a line, server responds with a line. You can then change your logic to follow that protocol.
0
jimmyraywvAuthor Commented:
>it is needed, readLine() reads until eol. you weren't writing one.

Perhaps i was not, but when I did, it did not change the observable behavior.  When I changed my write code to shutdown the output stream, I was able to get more reliable behavior.

Thanks for our help.
private static void write() throws Throwable {
		socket.getOutputStream().flush();
		PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
		out.println("INVOICE::QUOTATION");
		out.flush();
		System.out.println("WROTE_CLIENT_DATA");
		if (!socket.isOutputShutdown()) {
			System.out.println("SHUTTING_DOWN_CLIENT_OUTPUT");
			socket.shutdownOutput();
		}
	}

Open in new window

0
Mick BarryJava DeveloperCommented:
> Perhaps i was not, but when I did, it did not change the observable behavior.

thats because it wasn't the only problem as I mentioned in my comment above
and you client *does* write first already :)
0
Mick BarryJava DeveloperCommented:
> When I changed my write code to shutdown the output stream, I was able to get more reliable behavior.

which is what I suggested. Glad it worked for you :)
0
CEHJCommented:
:-)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.