hey
As part of a project ive had to write a small IRC client to embed in it. Everything works nicely until the program is closed and the thread that reads input from the IRC channel is waiting for more input and never dies.
while(((inBuffer=in.readLine())!=null)&&(die==false))
inBuffer is simply a string and in is a buffered reader on the socket.
the die variable is a boolean and my thought was that i can set that to true and it will fall out the thread. The problem is that "inBuffer=in.readLine()" is sitting there until it gets another line.
Can someone give me a hand?
Close the in stream, readLine() should then return null instantly.
You could set a timeout on the socket and if you get a timeout exception, you can poll a abort-flag. If it's unset, try again to read.
Shutdown the socket for input. That will deliver a null to the readLine() invocation and terminate the loop.
forgot bufferedReader had a "ready()" method to test if it has anything in the buffer. testing this did the trick.
Related
I'm developing a distributed system that receives requests via Socket and writes the results back using OutputStream.
I'm facing problems because I have to return a very large string, but Java just keeps the execution of the code after I call the method print() without it finished printing:
public void attendRequisition(Socket clientSocket) {
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream());
pw.print(getResults());
pw.close()
}
Some information:
I need to close the connection after sending the results.
Without the close() instruction, the whole printing process takes about 3~5 seconds to finishes
I'm using telnet to test this method, and I can see the message coming and being cut becase of Java running the close() instruction
I can't count with receiving client's feedback
I believe this is happening because Java thinks the method print() finished executing, but what might be happening is that Java sends the message to the JVM, and JVM send it to the network adapter, and since the message is very large, close() method is called before the network adapter is able to send the entire message.
What I need is a way to make sure Java will only run the instruction close() after the printing process finished and the client received the entire message.
UPDATE: I was able to get it working properly by adding a Thread.sleep(). By doing this, the SO has enough time to send the message before Java closes the connection. But I don't want to use this solution, it implicates on too many problems.
I was able to solve the problem using DataOutputStream.writeBytes(). This way, the execution only continues when the method finishes sending the data. It is slower, but works.
I'll bet that if you use another constructor (i.e., the one whose 2nd argument is a boolean to indicate your desire to flush) then your example will work. The way you're constructing the object, autoflush is disabled.
If your real code is more complex, then you can call pw.flush() at the appropriate moments.
I can see the message coming and being cut becase of Java running the close() instruction
No you can't. You can see the message being cut, unless you're wrong about how long it is, but you're jumping to conclusions about the reason. Java does not close the PrintWriter before it has finished sending. It flushes the writer to the socket send buffer, blocking if necessary, and then closes the underlying socket, which buffers a FIN behind the data. All the data gets sent, and all the data gets received, before the FIN arrives, which signals end of stream to the receiver.
Possibly you are unaware that PrintWriter swallows exceptions and therefore should really not be used over a network.
I am trying to understand some things about threads in java, which I am very unfamiliar with. Unfortunately my example is too big for running code, but I'll try to specify my problem as well as possible.
One of two similar code segments (taken from a little example which features a simple ChatClient/Server class), which are the center of my question:
public void run(){
String message;
try{
while((message = reader.readLine()) != null){
tellEveryone(message);
}
}catch(Exception ex){...}
}
(Taken from an inner class of the Server class.)
The server is waiting in a while(true) loop for clients via its serversockets accept() method and whenever a client connects, a new Thread is started with the above run method as "entry point".
What I don't understand is why this works. My understanding until now was that Thread which is supposed to constantly listen to something has to contain a while(true) construct because otherwise it would just finish it's run method and it would be finished with no return ("dead" call stack).
So for my example when reader gave us all lines he had to give in the beginning, I supposed it would leave the run()-method and nothing would happen when the specific client would send a new message but it seems it stays listening for client input. How does that work?
(I probably should say that "reader" is a BufferedReader within the inner class which is instantiated once for every connected client.)
I hope that was sufficiently explained. If more Information is needed I will gladly provide it.
readLine() blocks while there is no data. It only returns null at end of stream, which in the case of a socket means that the peer has disconnected.
If the client does not send anything, the server socket does not have anything to read. When the client writes to the socket and the contents are sent the reader can read the contents
I have 'n' server threads, and each one listen to 1 client.
When a server thread receives a message from its client, it needs to notify the other 'n-1' clients, and that's the reason why I keep a shared object (containing an array of 'n' sockets, one for each client) between the server threads.
Moreover, in the main server thread that holds the ServerSocket, every time I accept a new connection with a client I open a BufferedWriter/Reader to give a first answer to him using the new socket returned from ServerSocket.accept().
In case of an "OK" answer I open a new thread passing the new socket to it, in order to listen to the new client's following requests.
The problem is that i cannot close the BufferedReader and the BufferedWriter in the main server thread, because it will also close the underlying stream, causing problems to the server thread that is listening to that socket/stream.
And the question: if I open another BufferedReader (bound to the same socket) in the new thread, and then close it, will other BufferedReaders(Writers) ( specifically the ones opened in the main server thread, that i couldn't close before ) opened on the same socket be closed? Will an exception be thrown on them?
It could be possible to share the opened BufferedReader / Writer instead of the socket, to avoid instantiating every time a new object, but this is a question related to what could happen if i do things in the way described above.
Please tell me if I hadn't been clear, my english is not really good.
Closing any Reader or Writer or stream wrapped around a stream closes the wrapped stream.
Closing either the input stream or the output stream of a socket closes the other stream and the socket.
Closing the socket closes both streams.
In other words closing any of it closes all of it.
As noted in comments, multiple buffered streams/Readers/Writers wrapped around a single stream cannot work.
Multiple threads reading from/writing to the same socket is unlikely to work correctly either, unless you take great care with synchronization and buffering.
You should not do any I/O with an accepted socket in the accept loop. Otherwise you can block, which affects further clients.
You need to rethink your design.
Each Socket with an open connection to another Socket has an open InputStream and an open OutputStream. Closing either one of these streams will also close the socket. Closing a socket or its streams will not affect other sockets unless they are connected. You don't want to close any streams unless you also want to close the connection between the sockets using the streams. Please ask if there is something i missed or if you have other questions :)
I'm trying to implement asynchronous input reading from console in Java.
Basically, I want to do this:
Spawn a thread T which reads on standard input with a readLine() on a BufferedReader
Continue with the program
After 10 seconds, stop T
The problem is the readLine() call in T, which I haven't been able to block.
Since interrupting the thread does not work, I figured I would try and send data to standard input from code, to unblock the readLine().
So I tried the following: after 10 seconds, do
FileOutputStream os = new FileOutputStream(FileDescriptor.in);
os.write("Unblocking line\n");
I thought it would work like this: I'm writing to the standard input as in a pipe, so the code in T should read "Unblocking line\n" and go to the next instruction.
Too bad, this doesn't work: "Unblocking line" is immediately shown on screen as if it was written to standard output, and it doesn't seem to affect the readLine().
So my questions are:
Why is my reasoning wrong?
Is there a simple, clean method to achieve what I want to do? Please note that I'm aware of this solution. Also, please do not suggest using System.setIn: it doesn't work. Finally, I should clarify what I mean by simple and clean: using only threads, and avoiding busy waiting.
Thanks in advance.
EDIT: I don't want to close the standard input, as I want to read again after step #3.
Have you tried to simply call
System.in.close() ?
readLine() has to wait for a user to enter some thing. forever if nothing entered.
In your case, you want the thread to close automatically after 10 seconds if nothing entered I think!
code your thread accordingly. Instead of waiting forever if 10 seconds went without user entering an input then main thread should close input waiting thread.
I'm trying to make a server socket to listen to a client input stream but when i execute the start_listening() method, my program gets stuck. I even tried to remove the loop, but i still have the same problem. i guess that it waits for the client interaction. is there an alternative way to listen while the program is also working?
public static void start_listening(){
listener = new ServerSocket(9090);
while (true) {
Socket socket = listener.accept();
ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
us = (User) in.readObject();
}
}
When using the sockets technique, accept() blocks the execution of the current thread until a client connects to the listening socket. This is a defined behavior. Java documentation says: "The method [accept()] blocks until a connection is made." Have the server run within a endless loop can be ok.
So, to get this whole thing run you might want to take a look at this socket example which uses threads. Inside the run() method of ConnectionHandler you would deal with your User object.
Besides that the loop never ends (I suppose you will break at some point), you should do that kind of stuff in a separate Thread or an AsyncTask, doing accept in the main thread makes Andriod freeze until somebody connects to the socket. That's why your program gets stuck.
You might just use a Boolean flag to indicate when to end the while loop.Other wise the loop keep iteration as it never breaks.
while (true) { //will it ever breaks ??
}