Synchronizing methods in RXTX - java

Situation:
I'm trying to make the incoming data from SerialPort usefull for my purposes. In one class Processor.java I've implemented several methods - one of them (serialEvent) implements gnu.io.SerialPortEventListener. It stores the information read from inputStream in a buffer which is a byte array. There is also a method, which writes data to outputStream.
Problem:
I want to implement a method (in the same class) which will write something to outputStream depending on the messages read from the inputStream.
Pseudo code:
#Override
public void serialEvent(SerialPortEvent event) {
// get data
}
public void writeData(String dataToWrite) {
// write data
}
public void respond() {
// write data
// wait for appropriate response (read data)
// write data
// ...
}
How can I do this?

Only thing that comes to mind is a background thread that waits for input-buffer-full condition to process the received message and responds to it.
If you are communicating in fixed length packets or start-stop marked packets you should create a thread that would monitor the serial port, buffer the received data and once a "packet/message complete" condition is met to fire an event to a registered listener (in another thread if possible). That listener would then process the message and respond (in its own thread).

Related

How to handle tcp inputstream correctly - Java/Android

I'm creating an android application that needs a permanent TCP-Connection to a Server.
I've created a Service that establishes the Connection and listens for incoming Bytes on the Inputstream (The service runs in the background).
public class TCPServiceConnection extends Service{
//variables......
//...............
public void onCreate() {
establishTCPConnection():
}
The first 4 incoming bytes symbolize the message-length of a complete Message.
After reading a complete Message from the Inputstream into a separate buffer, I want to call another Service/Asynctask in a separate Thread that analyses the Message. (The service should continue listening for further incoming messages).
public handleTCPInput() {
while(tcp_socket.isConnected()) {
byte[] buffer = readCompletemessagefromTCPInputstream;
calltoAnotherThreadToanalyzeReceivedMessage(buffer);
}
//handle exceptions.......
}
Is there an existing Messagequeue-system in Android/Java that already handles the multi-access onto my separated byte[] buffer ?
To implement this I suggest you start a handler thread which will continuously read from the input stream.
As soon it has read the incoming message, it passes it to main thread using handler.
For eg. handler.sendMessage()
Now since this processing is not a heavy operation you can decide main/UI thread to process this information or you can start a async task to do it.

How to keep data with each channel on NIO Server

I have a Java NIO server which receives data from clients.
When a channel is ready for read i.e key.isReadable() return true read(key) is called to read data.
Currently I am using a single read buffer for all channels and in read() method , I clear the buffer and read into it and then finally put into a byte array , supposing that I will get all data in one shot.
But let's say I do not get complete data in one shot(I have special characters at data ending to detect).
Problem :
So now how to keep this partial data with channel or how to deal with partial read problem ? or globally ?
I read somewhere attachments are not good.
Take a look at the Reactor pattern. Here is a link to basic implementation by professor Doug Lea:
http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf
The idea is to have single reactor thread which blocks on Selector call. Once there are IO events ready, reactor thread dispatches the events to appropriate handlers.
In pdf above, there is inner class Acceptor within Reactor which accepts new connections.
Author uses single handler for read and write events and maintains state of this handler. I prefer to have separate handlers for reads and writes but this is not as easy to work with as with 'state machine'. There can be only one Attachment per event, so some kind of injection is needed to switch read/write handlers.
To maintain state between subsequent read/writes you will have to do couple of things:
Introduce custom protocol which tells you when the message is fully read
Have timeout or cleanup mechanism for stale connections
Maintain client specific sessions
So, you can do something like this:
public class Reactor implements Runnable{
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
public Reactor(int port) throws IOException {
serverSocketChannel.socket().bind(new InetSocketAddress(port));
serverSocketChannel.configureBlocking(false);
// let Reactor handle new connection events
registerAcceptor();
}
/**
* Registers Acceptor as handler for new client connections.
*
* #throws ClosedChannelException
*/
private void registerAcceptor() throws ClosedChannelException {
SelectionKey selectionKey0 = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
selectionKey0.attach(new Acceptor());
}
#Override
public void run(){
while(!Thread.interrupted()){
startReactorLoop();
}
}
private void startReactorLoop() {
try {
// wait for new events for each registered or new clients
selector.select();
// get selection keys for pending events
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> selectedKeysIterator = selectedKeys.iterator();
while (selectedKeysIterator.hasNext()) {
// dispatch even to handler for the given key
dispatch(selectedKeysIterator.next());
// remove dispatched key from the collection
selectedKeysIterator.remove();
}
} catch (IOException e) {
// TODO add handling of this exception
e.printStackTrace();
}
}
private void dispatch(SelectionKey interestedEvent) {
if (interestedEvent.attachment() != null) {
EventHandler handler = (EventHandler) interestedEvent.attachment();
handler.processEvent();
}
}
private class Acceptor implements EventHandler {
#Override
public void processEvent() {
try {
SocketChannel clientConnection = serverSocketChannel.accept();
if (clientConnection != null) {
registerChannel(clientConnection);
}
} catch (IOException e) {e.printStackTrace();}
}
/**
* Save Channel - key association - in Map perhaps.
* This is required for subsequent/partial reads/writes
*/
private void registerChannel(SocketChannel clientChannel) {
// notify injection mechanism of new connection (so it can activate Read Handler)
}
Once read event is handled, notify injection mechanism that write handler can be injected.
New instances of read and write handlers are created by the injection mechanism once, when new Connection is available. This injection mechanism switches handlers as needed. Lookup of handlers for each Channel is done from the Map that is filled at the connection Acceptance by the method `registerChannel().
Read and write handlers have ByteBuffer instances, and since each Socket Channel has its own pair of handlers, you can now maintain state between partial reads and writes.
Two tips to improve performance:
Try to do first read immediately when connection is accepted. Only if you don't read enough data as defined by header in your custom protocol, register Channel interest for read events.
Try to do write first without registering interest for write events and only if you don't write all the data, register interest for
write.
This will reduce number of Selector wakeups.
Something like this:
SocketChannel socketChannel;
byte[] outData;
final static int MAX_OUTPUT = 1024;
ByteBuffer output = ByteBuffer.allocate(MAX_OUTPUT);
// if message was not written fully
if (socketChannel.write(output) < messageSize()) {
// register interest for write event
SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_WRITE);
selectionKey.attach(writeHandler);
selector.wakeup();
}
Finally, there should be timed Task which checks if Connections are still alive/SelectionKeys are canceled. If client breaks TCP connection, server will usually not know of this. As a result, there will be number of Event handlers in memory, bind as Attachments to stale connections which will result with memory leak.
This is the reason why you may say Attachments are not good, but the issue can be dealt with.
To deal with this here are two simple ways:
TCP keep alive could be enabled
periodic task could check timestamp of last activity on the given Channel. If it is idle for to long, server should terminate connection.
There's an ancient and very inaccurate NIO blog from someone at Amazon where it is wrongly asserted that key attachments are memory leaks. Complete and utter BS. Not even logical. This is also the one where he asserts you need all kinds of supplementary queues. Never had to do that yet, in about 13 years of NIO.
What you need is a ByteBuffer per channel, or possibly two, one for read and one for write. You can store a single one as the attachment itself: if you want two, or have other data to store, you need to define yourself a Session class that contains both buffers and whatever else you want to associate with the channel, for example client credentials, and use the Session object as the attachment.
You really can't get very far in NIO with a single buffer for all channels.

Call a method of all parallel Class Threads

I have a question for you.
I have multiple Threads runnings of a class called ServerThread. When an specific event happens on ANY of those threads, I want to call a method of every other thread running in parallel.
public class ServerThread implements Runnable {
private TCPsocket clientSocket;
public ServerThread(Socket comSocket){
clientSocket = new TCPsocket(comSocket);
}
#Override
public void run(){
boolean waiting = true;
Message msg;
try{
while(waiting){
msg = clientSocket.getMessage();
shareMessage(msg);
}
}catch(Exception e){
ErrorLogger.toFile("EndConnection", e.toString());
}
}
public void shareMessage(Message msg){
clientSocket.sendMessage(msg);
}
}
I am talking about this specific line
shareMessage(msg);
which I would like to be called on every thread/instance
-- so that a message is sent to every client (in all tcp connections)
I've tried with synchronized but either I'm not using it well or that is not what I am looking for.
Another thing that might work is keeping a class with an static member which is a list of those tcpconnection objects and then do some loop in all every time.
Thanks for your help and time.
Edited with one possible solution
*Add an static array as a member of the class and add/remove objects of same class (or tcp sockets would also work)
private static ArrayList<ServerThread> handler;
...
handler.add(this);
...
handler.remove(this); //when client exists and thread stops
*Then create a method that iterates for each connection, and make it synchronized so that two threads won't interact at the same time. You may want to implement synchronized on your message sending methods as well.
public void shareMessage(Message msg){
//this.clientSocket.sendMessage(msg);
synchronized (handler){
for(ServerThread connection: handler){
try{
connection.clientSocket.sendMessage(msg);
} catch(Exception e){
connection.clientSocket.closeConnection();
}
}
}
}
First: synchronized is required to prevent race conditions when multiple threads want to call the same method and this method accesses/modifies shared data. So maybe (probably) you will need it somewhere but it does not provide you the functionality you require.
Second: You cannot command an other thread to call a method directly. It is not possible e.g. for ThreadA to call methodX in ThreadB.
I guess you have one thread per client. Probably each thread will block at clientSocket.getMessage() until the client sends a message. I don't know the implementation of TCPsocket but maybe it is possible to interrupt the thread. In this case you may need to catch a InterruptedException and ask some central data structure if the interrupt was caused because of a new shared message and to return the shared message.
Maybe it is also possible for TCPsocket.getMessage() to return, if no message was received for some time, in which case you would again have to ask a central data structure if there is a new shared message.
Maybe it is also possible to store all client connections in such a data structure and loop them every time, as you suggested. But keep in mind that the client might send a message at any time, maybe even at the exact same time when you try to send it the shared message received from another client. This might be no problem but this depends on your application. Also you have to consider that the message will also be shared with the client that sent it to your server in the first place…
Also take a look at java.util.concurrent and its subpackages, it is likely you find something useful there… ;-)
To summarize: There are many possibilities. Which one is the best depends on what you need. Please add some more detail to your question if you need more specific help.

Java Processing Messages Asynchronously in EJB Listener

I have a EJB Singleton that constantly listens for messages as a String and when a message arrives it processes the message for example storing to the database and doing other things.
Once I receive the message and after furthing processing, I need to asycnhrnously send the message. Java provides the ExecuteService to asynchronusly process the message. EJB also provides asynchronously processing through the #Asynchrnous annotation. The listener works by checking every couple of seconds to see if the message has arrived. Once the asynchronous method has been sent, a reply would come back in the form of an InputStream. I have two queries:
I have sample code:
#Startup
#Singleton
public class Processor {
#PostConstruct
public void init() {
while(true) {
Thread.sleep(1000);
if(!portIsOpen()) {
openPort();
listen();
}
else {
listen();
}
}
}
public void listen() {
// listens for messages, once the message arrives process them and then send asynchronously
Future<InputStream> inputStream = processAsynchrnously();
while(!inputStream.isDone()) {
// carry on with repeated requests
}
inputStream = inputStream.get();
// read this inputStream and turn into XML
}
#Asynchronous
public Future<InputStream> processAsynchronosly() {
// make an http connection and send the request of with the data as XML
return new AsychResult<InputStream>(httpUrlConnection.getInputStream());
}
}
The above is what I am trying to achive. However, the aim is to send the request asynchrnously and not wait but continue to receive other requests repeatly. The problem is the while(!inputStream.isDone()) this means it is blocked.
1) How can this be implemented in a different way so the while loop is not required.
2) When the data is available so the input stream is returned with the XML, in EJB is there a listener that can be invoked so that I will implement a method that will read the contents of the input stream? I am aware there are Inceptors but an Inceptor will not work in this case.
EDIT:
Please note the application is a TCIIP application, so it listens for messages on a port. It is not a RMI-IIOP application. This Singleton acts as a listener, so when the message arrives it processes it.
If MDB is the only solution how will MDB help? Could you show a code sample?

WriteListener (servlet 3.1) semantics

Let's say I'm writing chunks of data to an HttpServletResponse. So my method receives an array of bytes, I write it to response.getOutputStream(), and then I release the thread. When I receive another chunk of data, my method will be awaken, and it will write to getOutputStream() again. In the end, I call to AsyncContext.complete().
Now, the WriteListener.onWritePossible() spec says:
this method will be invoked by the container the first time when it is
possible to write data. The container will subsequently invoke the
onWritePossible method if and only if isReady method on
ServletOutputStream, described below, returns false.
It seems that when the container calls this method, I already need to have my response buffered somewhere, because onWritePossible() may never be called again. So, for the previous example, I need to write all chunks of data I receive in a buffer (a byte array, or maybe a temporary file if the buffer is big enough), and if onWritePossible() is called before my response is complete, what should I do? Block the thread until I have all my response data?
Check code in following link. May not be the exact solution but it's idea can be a solution for your case:
Servlet 3.1 Async IO Echo
hmm.. Maintaining a buffer seems to be the way
public void onWritePossible() throws IOException {
doWrite();
}
// this is some callback where you received next chunk of data
public void onMoreDataReceived(byte[] data) {
putDataToBuffer(data);
doWrite();
}
// this method is non-blocking
private void synchronized doWrite() throws IOException {
while (_servletOutputStream.isReady() && hasMoreDataInBuffer()) {
_servletOutputStream.write(getMoreBytesFromBuffer());
}
}

Categories

Resources