i want to read from input stream when i connect to a server socket.
but there may exist some delays between messages how can i read from input stream without busy loop ?
string mes = socketReader.readLine();
above line returns null when no input provided in socket input stream.
i want to be notified somehow when a message is ready in input stream.
tnx
Have you looked asynchronous IO?
In a GUI context, SwingWorker may help: let doInBackground() do the reading, use process() for interim reuslts, and done() to wrap up. You can register a PropertyChangeListener to drive a progress indicator. This article expands on the idea, and a back port to Java 1.5 is available. Here's a simple example that reads from a JDBC source instead of a stream, but the idea is the same.
Related
I'm trying to write a socket server in java using the java nio classes. Only using non-blocking io, not async io.
I've got a single thread which calls the selector's select() method. Initially the only channel in the select list is a ServerSocketChannel. Each time select() returns I enumerate the selectedKeys() list and delegate the io to a separate io thread. Before I send the information to the io thread I first attempt to turn off the interest on the channel by setting the interestOps to zero. I do this so that the select() isn't firing anymore on that channel since it should continue to fire until the io has been performed. By the way, you can't accomplish this via the SelectionKey's cancel() method as that puts the channel on the cancelled list and it can't be added back to the selection list. cancel() is only for removing the channel from the list when you're done with it. I don't use cancel() at all since closing the socket() will automatically call cancel().
When the io thread finishes the io it communicates back to the select thread asking it to either close the socket or reset the interestOps to what they should be.
While this seems to be somewhat working, I've noticed that select() seems to continually return socket channels even when there are no bytes to read. By the way, the server is only reading from the socket and only sets the interest to OP_READ (or zero when I want to turn off the channel). To test a specific scenario I wrote a client which opens a socket, writes 1k bytes to it, sleeps 10 seconds, and then writes another 1k bytes to it then closes the socket. During this sleep time the select() call returns continuously and when I read the socket there are zero bytes returned. Obviously I don't want the select() loop firing continuously when there is no work to do as I would be pegging a CPU. I've set the channel up for non-blocking io. I should also mention that, similar to one of the threads I reference below, this behavior doesn't happen until the client opens the socket and starts sending data. In this case I still have the server socket channel I'm listening on for OP_ACCEPT and the select() call is not constantly firing for that.
Here are two similar, but different, threads:
Infinite loop with Selector even there's no connection from client
Java Selector returns SelectionKey with OP_READ without data in infinity loop after writing to channel
Some of the comments in those two threads talk about handling the EOF, -1 on read(), case. This is not the issue I'm having so please don't mark this as a duplicate of those.
Also, in one of those threads it sounded like someone suggested that since the socket channel is in non-blocking mode the select() will fire continuously regardless of whether there is, in my case data to read. This sounds very odd. I would find it hard to believe this is the way it's supposed to be working. I believe when I indicate I have an interest in read on a channel, select() should only return that channel in the selected list if there is data to read.
Thanks,
Nick
It sounds like you aren't removing the selected key from the selected-key set while iterating. There are several examples of doing it correctly in the threads you linked.
NB one of them states that select() will loop indefinitely if there are no events. That will only happen if there is a positive timeout value: it will timeout and return zero, repeatedly. If there is no timeout it will block indefinitely.
NB cancel() doesn't actually prevent you from adding the channel back to the selection list. You would have to re-register the channel, and there might be an issue if select() hasn't executed between the cancel and the re-registration (as it may not have processed its internal cancel list). But there's nothing wrong with the way you're doing it now.
I have a very simple question.
Based on Java I/O scheme, whenever a thread is waiting for some data, so it will be blocked? is it true? something like this.
byte[] _buff=new byte[1024];
int _r=_in.read(_buff);//it blocks until some data is available
and the just possible way to give up reading is closing the stream by another thread, is it right? something like this.
void run(){
_in.close();
}
so if I am right with above scenarios, so why this is impossible just interrupt a thread which is reading from System.in by closing the stream. I run a thread that just waits for 5 seconds then wants to interrupt/give up rest of the reading from the stream.
void _read_data(){
System.out.print("enter y to save the workspace ");
new Thread(_cancel_thread).start();
int _r=System.in.read();//blocks
}
///////////
void run(){
try{
Thread.sleep(5000);
System.in.close();//doesn't work.
}catch(Exception _ex){}
}
Questions:
1.How to close the stream?! why the closing stream thread cannot close the stream?!
2.Once the stream got closed, how to open it again?!
For the first question, I think this is because maybe(I don't know, not sure) the stream is kinda locked by lower-level, so while it's locked, another thread is just waiting to acquire the lock and close it.
and for second one, I really don't know is there any class(stream) which works with keyboard stream or not, but why do you really want to close it? just keep the stream somewhere (like in=System.in), then redirect the standard stream to another stream by calling System.setIn(newStream), then whenever you want to give keyboard stream back, reset the stream with the reference.
Closing the default system input stream is not good idea, I suggest you utilize either JConsol or jNativeHook, these guys do not block, instead they listen for events.
Is there any possibility to communicate with clients by events? I mean:
I have connected client, InputStreamReader and PrintWriter
in = new BufferedReader(new InputStreamReader(
client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
when I use in.readLine() server waits for incoming data. But i have this situation:
Client didn't send any data
Connection is still alive
I need to send some data to client (but in.readLine() is still hanging process) and wait for respond
The questions are:
What is the best way to handle asynchronously incoming data? I mean something like "events". Should I create thread for read and another thread for write? If i can do it in one thread, could you give an example of the code please?
Is possible to abort waiting for in.readLine()?
Java provides non-blocking i/o through the java.nio package (see here). But Java's "nio" channels do not inter-operate with streams from java.io. So, if you want to use nio, you'll have to build your server with nio from the listener on down.
If you're stuck with the existing java.io streams, then you'll either have to use a thread-per-client model; or you'll need to devise a system for having a single thread (or pool of threads) manage a bunch of clients by looping over them repeatedly, polling instream.available() to figure out which ones have data ready to be handled. Of course, in this latter case, you'd want to avoid busy-looping, so some appropriate use of Thread.sleep is probably also in-order.
In my opinion having a separate thread to perform socket IO is best if you want your program to behave asynchronously. Have a look at http://en.wikipedia.org/wiki/Observer_pattern.
For a simple application, what I'll do is create a separate thread to listen for incoming data, and register 'observers' or 'event listener' to this thread. When a data comes in, notify your observers so they can perform necessary actions.
While the listener thread is idle waiting for data, your main thread still can progress normally.
Make sure you're also familiar with Java concurrency programming
I'm programming a simple Java NIO server and have a little headache: I get normal InputStreams i need to pipe to my clients. I have a single thread performing all writes, so this creates a problem: if the InputStream blocks, all other connection writing will be paused.
I can use InputStream.available() to check if there are any incoming data I can read without blocking, but if I've reached end-of-stream it seems I must call read() to know.
This creates a major headache for me, but I can't possibly believe I'm the first to have this problem.
The only options I've come up with so far:
Have a separate thread for each InputStream, however that's just silly since I'm using non-blocking I/O in the first place. I could also have a thread pool doing this but then again that limits the amount of simultaneous clients I can pipe the InputStream to.
Have a separate thread reading these streams with a timeout (using another thread to interrupt if reading has lasted longer than a certain amount of time), but that'll most certainly choke the data flow should I have many open InputStreams not delivering data.
Of course, if there was a magic InputStream.isEof() or isClosed() then this wouldn't be any problem at all :'(
".....Have a separate thread for each InputStream, however that's just silly since I'm using non-blocking I/O in the first place...."
It's not silly at all. First you need to check whether you can retrieve a SelectableChannel from your InputStream implementation. If it does you are lucky and you can just register it with a selector and do as usual. But chances are that your InputStream may have a channel that's not a SelectableChannel, in which case "Have a separate thread for each InputStream" is the obvious thing to do and probably the right thing to do.
Note that there is a similar problem discussed in SO about not able to get a SelectableChannel from an inputstream. Unfortunately you are stuck.
I have a single thread performing all
writes
Have you stopped to consider whether that is part of the problem rather than part of the solution?
Is there an elegant way to fire an event when characters are available from System.in? I'd like to avoid polling InputStream.available().
You would have to create a separate thread that blocks in read until something is available.
If you don't want to actually eat up the input, you would have to wrap it with an internal buffer, read into the buffer, shout, and when asked for the input, give back data from the buffer.
You could solve it like this:
InputStream stdin = System.in;
// Create a wrapper (with it's own dedicated read-thread)
MyListenableInputStream listenableInputStream =
new MyListenableInputStream(stdin);
// Update System.in with something more useful.
System.setIn(listenableInputStream);
Sure...start a thread that blocks on the input and then calls your event method when it gets something.
Very generally speaking:
If you already have an event reactor running, create a thread and have it block on read(). When there's data available, have that thread enqueue an event for the reactor to process. If you can't do this, most event reactors provide an InvokeLater, or CallLater method, for you to run some code in the event processing thread.
After notifying or scheduling a function call, go back to blocking on read().
If you want something elegant you could easily implement an ObservableInputStream which accepts a Listener that gets warned about availability of data but you will have to implement it with an inner thread that periodically checks for data and call the listener in case.
Think about the fact that streams aren't supposed to be used as object that send small packets but a continuous stream of bytes, that's why this approach would work only if the data that is given to the input stream doesn't effectively arrives too often (otherwise it would keep calling the listener ad libitum). In addition you will have to care about consistency, if data arrive when something is already available and the listener is warned then something can take all the bytes (which you should place in a temporary buffer) but if there's more data that just arrived you should decide how to handle (give it together with buffer, place in buffer and call listener again, etc)
new Thread(){
public void run() {
while(System.in.get()){
}
}.start();