Java Socket - ObjectInputStream - java

Im calling ObjectInputStream all the time in while loop with statement true:
while(true){
//send data
}
but at moment when closing Socket, ObjectInputStream and rest i got multiple Exception Socket closed (actualy because i close it).
The question: what statement can i put in while loop to check ObjectInputStream is not closed?
Edit: Socket.isConnected() dont give good result
whole method
private void dataTransfer(){
try {
while(!con.isClosed()){
String message = (String) input.readObject();
ChatWindow.getMessage(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}

Your problem is probably multithreading asynchronization.
While the while runs outside the EDT, windowClosing() runs inside. Therefore it may check the isClosed() before windowClosing() was actually called, and execute the loop code after that.
As in similar cases, the best way is to use synchronization, but it's not the best idea in the EDT. Use a new thread in the windowClosing() method that closes the stream and synchronize that.

Related

objectinputstream available() returns 0

I am working on socket programming and implementing custom request response protocol. For same I have used ObjectInputstream and ObjectOutputstream in java socket API.
The area where I have stucked is to check if data(in my case object) is available to read or not, for this I have tried to use the ObjectInputstream.available() but it is returning 0 even if data is available on stream.
Why is it so?
So I have come up with solution: using exception and handling them in infinitely running loop, so even if exception(Read time out) occurs it will try to read again.
I have doubt is it good practice to do so? Or if any other solution you might have do suggest.
while (true){
try {
request = rpcClient.getRequest();
System.out.println(request);
// use threads to handle request for faster response(make use of request IDs)
rpcClient.sendResponse("test response");
} catch (SocketException e)
{// thrown when connection reset
System.out.println("Connection reset : Server is down.....");
break;
} catch (IOException e){
// thrown when read time out
System.out.println("read time out: listening again");
} catch (ClassNotFoundException e){
e.printStackTrace();
}
}
You shouldn't be using available() in the first place. Disable the read timeout, so you can just let the thread wait until there's something to read (or the connection is broken).
I wouldn't recommend using ObjectStreams for network communications though. It's not very suitable in most cases, considering the header information and other things that gets transferred. You're better off designing your own protocol to use and just send bytes over the network.
That is not a good practice since an infinite loop eats away your CPU time.
I dont quite understand your statement
but it is returning 0 even if data is available on stream
since that isnt the case. If it returns 0, there is no data that can be read from the stream. What makes you so sure there actually is data?
Also: I cant see the code that is calling available(). Could you edit your question?

'ServerSocket.accept()' Loop Without SocketTimeoutException (Java) (Alternative Solution)

Explanation
I'm revisiting the project I used to teach myself Java.
In this project I want to be able to stop the server from accepting new clients and then perform a few 'cleanup' operations before exiting the JVM.
In that project I used the following style for a client accept/handle loop:
//Exit loop by changing running to false and waiting up to 2 seconds
ServerSocket serverSocket = new ServerSocket(123);
serverSocket.setSoTimeout(2000);
Socket client;
while (running){ // 'running' is a private static boolean
try{
client = serverSocket.accept();
createComms(client); //Handles Connection in New Thread
} catch (IOException ex){
//Do Nothing
}
}
In this approach a SocketTimeoutException will be thrown every 2 seconds, if there are no clients connecting, and I don't like relying on exceptions for normal operation unless it's necessary.
I've been experimenting with the following style to try and minimise relying on Exceptions for normal operation:
//Exit loop by calling serverSocket.close()
ServerSocket serverSocket = new ServerSocket(123);
Socket client;
try{
while ((client = serverSocket.accept()) != null){
createComms(client); //Handles Connection in New Thread
}
} catch (IOException ex){
//Do Nothing
}
In this case my intention is that an Exception will only be thrown when I call serverSocket.close() or if something goes wrong.
Question
Is there any significant difference in the two approaches, or are they both viable solutions?
I'm totally self-taught so I have no idea if I've re-invented the wheel for no reason or if I've come up something good.
I've been lurking on SO for a while, this is the first time I've not been able to find what I need already.
Please feel free to suggest completely different approaches =3
The problem with second approach is that the server will die if an exception occurs in the while loop.
The first approach is better, though you might want to add logging exceptions using Log4j.
while (running){
try{
client = serverSocket.accept();
createComms(client);
} catch (IOException ex){
// Log errors
LOG.warn(ex,ex);
}
}
Non-blocking IO is what you're looking for. Instead of blocking until a SocketChannel (non-blocking alternative to Socket) is returned, it'll return null if there is currently no connection to accept.
This will allow you to remove the timeout, since nothing will be blocking.
You could also register a Selector, which informs you when there is a connection to accept or when there is data to read. I have a small example of that here, as well as a non-blocking ServerSocket that doesnt use a selector
EDIT: In case something goes wrong with my link, here is the example of non-blocking IO, without a selector, accepting a connection:
class Server {
public static void main(String[] args) throws Exception {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
while(true) {
SocketChannel sc = ssc.accept();
if(sc != null) {
//handle channel
}
}
}
}
The second approach is better (for the reasons you mentioned: relying on exceptions in normal program flow is not a good practise) allthough your code suggests that serverSocket.accept() can return null, which it can not. The method can throw all kinds of exceptions though (see the api-docs). You might want to catch those exceptions: a server should not go down without a very good reason.
I have been using the second approach with good success, but added some more code to make it more stable/reliable: see my take on it here (unit tests here). One of the 'cleanup' tasks to consider is to give some time to the threads that are handling the client communications so that these threads can finish or properly inform the client the connection will be closed. This prevents situations where the client is not sure if the server completed an important task before the connection was suddenly lost/closed.

Java Socket - how to catch Exception of BufferedReader.readline()

I have a Thread (let's say T1) which reads data from socket:
public void run() {
while (running) {
try {
BufferedReader reader = new BufferedReader( new InputStreamReader(socket.getInputStream()) );
String input = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Another Thread (lets say T2) try to finish the program in one of its method. Therefore T2 does the following:
T1.running = false;
socket.close();
Here is this scenario for which i couldn't find a solution:
T1 is active and waiting for some input to read i.e. blocking.
context switching
T2 is active and sets running to false, closes the socket
context switching
because T1 was blocking and T2 closed the socket, T1 throws an Exception. What i want is to catch this SocketException. i can't put a try/catch(SocketException) in T1.run(). So how can i catch it in T1's running-method? If it's not possible to catch it in T1's running, then how can i catch it elsewhere?
PS: "Another question about the Thread Debugging"
Normally when i debug the code step by step, i lose the 'active running line' on a context switch. Let's say i'm in line 20 of T1, context switch happens, let's assume the program continues from the 30.line of T2, but the debugger does not go/show to the 30.line of T2, instead the 'active running line' vanishes. So i lose the control over the code. I use Eclipse for Java and Visual Studio for C#. So what is the best way to track the code while debugging on a context switch ?
For your problem assuming you are using a Thread Pool maybe you should make a ThreadFactory that installs a Thread.UncaughtExceptionHandler on all Threads and then invoke your work with execute() on the ExecutorService instead of submit().
For you problem with debugging maybe you should read
http://msdn.microsoft.com/en-us/library/ms164746.aspx
Your code has several other problems so I'll address them all at the same time.
You must create the BufferedReader outside the loop. Otherwise you will lose data in the buffers being discarded each time around the loop.
You must test the result of readLine() for null. If you get it, you must close the BufferedReader and exit the loop.
If you get any exception you must also close the BufferedReader and exit the loop.
What i want is to catch this SocketException.
So catch it.
I can't put a try/catch(SocketException) in T1.run().
You must. No choice. You have to completely rewrite it anyway because of the above items.

What is the correct way to stop a thread waiting for network activity?

This question has no doubt been asked in various forms in the past, but not so much for a specific scenario.
What is the most correct way to stop a Thread that is blocking while waiting to receive a network message over UDP.
For example, say I have the following Thread:
public class ClientDiscoveryEngine extends Thread {
private final int PORT;
public ClientDiscoveryEngine(final int portNumber) {
PORT = portNumber;
}
#Override
public void run() {
try {
socket = new DatagramSocket(RECEIVE_PORT);
while (true) {
final byte[] data = new byte[256];
final DatagramPacket packet = new DatagramPacket(data, data.length);
socket.receive(packet);
}
} catch (SocketException e) {
// do stuff 1
} catch (IOException e) {
// do stuff 2
}
}
}
Now, would the more correct way be using the interrupt() method? For example adding the following method:
#Override
public void interrupt() {
super.interrupt();
// flip some state?
}
My only concern is, is socket.receive() not a non-interruptable blocking method? The one way that I have thought of would be to implement the interrupt method as above, in that method call socket.close() and then cater for it in the run method in the catch for the SocketException. Or maybe instead of while(true) use some state that gets flipped in the interrupt method. Is this the best way? Or is there a more elegant way?
Thanks
The receive method doesn't seem to be interruptible. You could close the socket: the javadoc says:
Any thread currently blocked in receive(java.net.DatagramPacket) upon
this socket will throw a SocketException
You could also use setSoTimeout to make the receive method block only for a small amount of time. After the method has returned, your thread can check if it has been interrupted, and retry to receive again for this small amount of time.
Read this answer Interrupting a thread that waits on a blocking action?
To stop a thread, you should not user neither interrupt nor stop in java. The best way, as you suggested by the end of your question, is to have the loop inside the main method controlled by a flag that you can rise as needed.
Here is an old link about this :
http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Other ways of stopping a thread are deprecated and don't provide as much control as this one. Also, this may have changed a bit with executor services, I didn't have time to learn much about it yet.
Also, if you want to avoid your thread to be blocked in some IO state, waiting for a socket, you should give your socket a connection and reading time out (method setSoTimeout).
Regards,
Stéphane
This is one of the easier ones. If it's blocked on a UDP socket, send the socket a UDP message that instructs the receiving thread to 'stop'.
Rgds,
Martin

How should I read from a buffered reader?

I have the following example of reading from a buffered reader:
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
The code in the loop println will be executed whenever something appears in the buffered reader (input in this case). In my case, if a client-application writes something to the socket, the code in the loop (in the server-application) will be executed.
But I do not understand how it works. inputLine = input.readLine() waits until something appears in the buffered reader and when something appears there it returns true and the code in the loop is executed. But when null can be returned.
There is another question. The above code was taken from a method which throws Exception and I use this code in the run method of the Thread. And when I try to put throws Exception before the run the compiler complains: overridden method does not throw exception. Without the throws exception I have another complain from the compiler: unreported exception. So, what can I do?
When the socket on the other end is closed, the reader should return a null string. This is the condition that you are looking for. To handle the exception, wrap the reading loop in a try/catch block.
try {
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
}
catch (IOException e) {
System.err.println("Error: " + e);
}
You might find this tutorial on reading/writing from/to a socket in Java, helpful.
For your first question:
But I do not understand how it works. inputLine = input.readLine() waits until something appears in the buffered reader and when something appears there it returns true and the code in the loop is executed. But when null can be returned.
BufferedReader.readLine() does not return true upon success. It returns a String containing the line that was read. If the end of the stream is reached, it returns null.
Your second question:
The above code was taken from a method which throws Exception and I use this code in the run method of the Thread. And when I try to put throws Exception before the run the compiler complains: overridden method does not throw exception. Without the throws exception I have another complain from the compiler: unreported exception. So, what can I do?
You should wrap your code in a try/catch block. If you don't want to handle the caught exception, simply leave that part blank (not recommended)
try {
while ((inputLine = input.readLine()) != null) {
System.out.println("I got a message from a client: " + inputLine);
}
} catch (Exception e) {
//handle exception
}
The reader's readLine() will return a string value when it has something read, an empty string when there isn't anything yet, and null when the connection is closed.
I would recommend wrapping a try/catch around your block of code with the IO function and handle errors appropriately.
input reader is connected to the socket, which is a listener, i.e. keeps listening to incoming messages.
About your second question, you should put a try/catch block inside the method, catch the Exception and handle it. Do not re-throw it.
But I do not understand how it works. .... waits until something appears in the
buffered reader and when something
appears there it returns true
No, it returns the value of the expression (inputLine = input.readLine()), the inputLine itself. The inputLine is compared to null.
null is returned when the "EOF (End Of File)" is reached. Since this is reading from a network socket, the end of file is created when the socket is disconnected (either by the server or the client), but you will likely get an Exception before you actually see the EOF.
If this isn't for homework, you might want to look at Apache Commons IOUtils.
Assuming you don't create the BufferedReader, and just stop at the InputStream:
String results = IOUtils.toString(inputStream);
System.out.println(results);
while ((inputLine = input.readLine()) != null) {
Look at each part of the expression:
input.readLine()
Returns a String which will be null if the end of the stream has been reached (or throws an Exception on error).
inputLine = input.readLine()
Assigns this String to inputLine
((inputLine = input.readLine()) != null)
Checks that the String that was assigned is not null (end of stream).
You have received some good answers. Just catch the exception and deal with it locally. If you need to pass this on to other code but cannot since the run() method does not allow for any check exception, you can wrap the exception in a RuntimeException of some kind. If the run method is executing directly on a Thread (since it is a Runnable probably) then you should take care with re-throwing a wrapped exception.
As for the result from readLine(), it will return null when there is nothing more to read. In the case of a socket this is when the other side cleanly closes the socket (any sudden termination or unclean close would typically result in an exception in your code as the OS will send a different kind of socket close notification).
I do have one word of caution since you are wrapping a socket in a java.io.BufferedReader. You should be very careful about using this in any kind of production code.
The danger is that BufferedReader does not deal well with exceptions in the midst of reading. This is especially an issue if you have enabled a timeout on the socket so the code will receive periodic exceptions automatically from the operating system. The timeout (or other exception) could come while the buffer inside the reader is filling. If you attempt to reuse the object after the exception, it will ignore any previous contents in the buffer. The packet(s) that were previously received are silently lost and there is no way to retrieve those bytes.
Note that there are other kinds of socket exceptions that do not mean that the socket has been lost. For instance, look at the definition of java.io.InterruptedIOException. This has a public variable that reports the number of bytes successfully transferred in the most recent I/O (read or write) request. This means that the IO operation can be executed again to retrieve or send the remaining bytes for the packet.
If upon any exception your design is to immediately close the reader and socket the method will work correctly.
The proper way to read from a socket is to use the socket stream directly, use NIO (ByteBuffers and such), or use a well written network library with good abstractions over these lower level classes (several open source ones are available).

Categories

Resources