Interrupt blocking network IO without closing the socket - java

I read from a stream created by Socket.getInputStream(). When I use it, it blocks until it gets new data(exactly what it should). Now I need the stream to read something (see below). But when I start a new read it will give me unspecified output(or not?). My question is:
How can I interrupt the actual read, so I can use the read method?
Details: I connect to a server and send commands to it. From time to time the server sends messages to my client (event notifications), which I need to register. I want to be able to send commands while I'm waiting for this messages. When I send a command the answer to this command is read from the stream. And here is the problem: I'm still listening to the messages while I try to read my answer. So I need something that interrupts the current read.

The problem with stopping the event processor from reading is that you introduce a race condition: What happens if the server sends an event right after you terminated the read? The "response" that you read would wind up being an event.
The proper way to do this is to do all your reading, both events and responses, in one place and handle the responses like an event also. Right before you send a command, register a listener for the response, then send the command. When the reading thread sees a response, have it find the proper listener and notify it that the response has been received.

Easiest, best way to handle this IMO is to use an asynchronous listener with event callbacks. DataFetcher is an implementation (Also see Timeout and PartialReadException, dependencies in the same project/package, and IOUtils, which has capabilities to directly connect a FetcherListener with an InputStream)

Related

How to wait on different events simultaneously

I have an open socket connection to a server.
On the one hand, in my code, I want to wait on a BlockingQueue for a message to be handed to me for sending to that server, then write it to the OutputStream.
When I send such a message, this normally expects an answer from the server (which needs to be read from the InputStream).
At the same time, I want to continuously listen on the socket's InputStream for spontaneous incoming messages from the server (server generated events).
Is there a recommended pattern for handling such a situation?
I obviously expect to have at least 2 threads involved (waiting on the two inputs - BlockingQueue and Socket). Any pointers are welcome on how to sync those, links to docs/blogs welcome.

Closing the channel right after writing the response

What happens if I close the channel right after writing the response? Is the response still delivered?
This http upload example seems to say that but I'm not sure if it's just a bug.
writeResponse(ctx.channel());
ctx.channel().close();
If you close a channel using .close() just after writing, then you create a race condition in with either all the data is written, half of the data, or even none, depending on the length of the message.
This happens because all written messages end up into a queue, and depending if the current thread is a Netty thread or not, it either processes the data directory, or just returns.
Since in most conditions you only want to close the channel after all writes as completed, you should use the following code when writing your response:
ctx.writeAndFlush(protocolSpecificPacket)
.addListener(ChannelFutureListener.CLOSE);
While this always works, you don't always have access to the last write, in these cases you can also send an empty ByteBuf, and then add the listener to that:
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
No it not a bug,but not the best way to close channel,I assume you writeResponse perform like this:
ctx.channel().write(msg)
It's sent asynchronisly,actuallay the message will offer to a writeBufferQueue,and the write IO thread will be wake up to do the actual write.
Check the ChannelFuture returned by ctx.channel().write(msg),you can wait on that object.
the best way to close a netty channel,I think,would be :
ctx.channel().write(a emptybuffer).addFutureListener(Channels.CloseFuture);
since you are using netty 4.0,you may neeed to search something similar with above.

Listener for incoming messages

I am currently trying to create a chat application using the Socket and ServerSocket classes, but i kinda ran into a roadblock. I need some kind of listener to execute a certain block of code when a message is incoming from the server or the client, but i can't seem to find one. An option would of course be to just check for incoming messages every 10 ms or something, but isn't there a smarter solution?
In general, you should assign a Thread to each Socket you are reading, so that Thread can block on the socket and wait for incoming information.
You should take a look at DataFetcher: http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/
This class can work asynchronously, and notify a FetcherListener when new data is available
I recommend Netty or Mina. As for Socket and ServerSocket, the read() calls are blocked, so in a way the code below the read()s are executed whenever there's incoming data.
Beware of the incomplete message though, because Sockets provide a stream of bytes and the applications are usually more comfortable with discrete messages.

Netty : Blocking call to get a connected Server Channel?

The call on ServerBootstrap.bind() returns a Channel but this is not in a Connected status and thus cannot be used for writing to client.
All the examples in Netty documentation show writing to a Channel from its ChannelHandler's events like channelConnected - I want to be able to get a connected Channel not in the event but as a reference outside the event , lets say some client code using my server component. One way is to manually code for waiting for channelConnected event and then copying the Channel reference.But this may be reinventing the wheel.
So the question is : Is there a blocking call available in Netty that returns a Connected Channel ?
edit : I am using Oio Channels , not Nio.
You could create a blocking call, but I think you maligned the event based approach too quickly. This is a contrived example, just to make sure I understand what you're trying to do:
Netty Server starts
A DataPusher service starts.
When a client connects, the DataPusher grabs a reference to the client channel and writes some data to it.
The client receives the pushed data shortly after connecting.
More or less correct ?
To do this, your DataPusher (or better yet, one of its minions) can be registered as a ChannelHandler in the server pipeline you create. Make it extend org.jboss.netty.channel.SimpleChannelHandler. The handler might look like this:
DataPusher dataPusher = getMyDataPusherReference();
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
dataPusher.doYourThing(e.getChannel()); // do something in another thread....
}
If you are determined to make it a blocking call from the DataPusher's perspective, just have it wait on a latch and have the minion drop the latch.
Not sure if that's what your'e looking for.....
After all the exchanges above, I still don't see that any of this is necessary.
Surely all you have to do is just accept the connection from the external service; don't register it for any events; then, when the other client connects, register for I/O events on both channels.
The external service doesn't know or care whether you are blocked in a thread waiting for another connection, or just not responding for some other reason.
If he's writing to you, his writes will succeed anyway, up to the size of your socket receive buffer, whether you are blocking or not, as long as you aren't actually reading from him. When that buffer fills up, he will block until you read some of it.
If he is reading from you, he will block until you send something, and again what you are doing in the meantime is invisible to him.
So I think you just need to simplify your thinking, and align it more with the wonderful world of non-blocking I/O.

Handling Java Interupts

I am making an application that will work much like a real time chat. A user will be constantly writing on lets say a text area and messages will be send to other users. On the communications class I have set up a receiver. When a message from someone reaches the client, the receive method will be invoked and will get the message. What I can't understand is how the code will be executed. What happens if, while the user is typing/sending a message the receive message is invoked ? What do I need to do in order for this to work properly ?
Hope the question is clear enough.
ps : Im still in the design phase thats why I haven't tested it to see what happens.
Also atm I only use a second thread to receive messages which calls the receive method.
There should not be a problem at all.
When a message from someone reaches the client, the receive method
will be invoked and will get the message. What I can't understand is
how the code will be executed?
You should have a Receiver class that will encapsulate a socket (from which your receive data) and keep a set of listeners (see Observer pattern). A GUI can be one of the listeners. When a message is received via the socket, you need to notify all listeners by forwarding the data received. This way, you have a clean and nice way to notify the GUI about new messages arrivals.
What happens if, while the user is typing/sending a message the
receive message is invoked ?
This depends on the type of IP protocol you are using but in general your don't have to worry about this although I suggest you protect your sockets using lock mechanisms.
What do I need to do in order for this to work properly ?
Here is a nice example that can give you some inspiration :)
EDIT: As for your question regarding execution flow, sending and receiving are two different and uncorrelated operations that can happen at the same time. This can be achieved by implementing send and receive operations in two different threads. Here is an article on socket communications and multithreading.
You should either do what traditional Java EE app servers have done, which is assign a separate thread for processing each incoming message, or try a Java NIO solution along the lines of Netty.

Categories