I am stuck in a strange issue while reading data from serial port in Java.
I have to read data from serial port via a polling method in a thread which is working fine, but I have a requirement where I need to write data to a serial port and read ACK back. Writing data to the serial port is successful but I am not able to read data back. Here there are two read operations one in thread and one in main thread.
Once I receive serial write data I paused the thread which is reading data from the serial port using a flag and started reading data from serial port again once write is done, but I am not able to read data. I disabled reading serial port after write operation and enabled thread which reads serial port in thread, here I am seeing ACK data from serial port.
Can any suggest what is going on wrong with this serial read operation? It is not buffered read/write operation.
I strongly recommend using only one dedicated thread for accessing serial port reading. The most reliable solution used to be an interrupt handler shoveling all the received data to a threadsafe state machine. Trying to read the serial port from multiple threads calls for problems. Serial port IO doesn't care that you "paused your thread", the data can be already fetched in and lost due to context switch.
So simply keep reading what comes in and if ACK is expected and obtained, inform the main thread via semaphore. In a dirty brutally simplified pseudocode:
Main thread loop:
{
serialReaderThread.isAckExpected = true
sendWriteCommand();
ackReceivedSemaphore.wait();
}
Serial reader thread loop:
{
readData();
if( isAckExpected && data == ack ) {
mainThread.ackReceivedSemaphore.notify();
isAckExpected = false
}
}
You need to set isAckExpected before sending the write command, because if your serial peer is fast enough, you might get the response back before your sendWriteCommand even returns.
You should not have different threads attempting to read from the serial port. The correct architecture is to have the single thread do the reading and distribute the incoming data to interested clients via multiple queues.
You would have a "normal read processing" thread that is given data by the read thread. When you need to do the write/ack sequence, the thread doing the write/ack would temporarily register itself with the read thread and divert the data stream.
You still have to deal with any interleaving of data (i.e. normal data being received after the write request but before the ack is received), but that is up to your application.
Related
I am trying to use SocketChannel.write and SocketChannel.read at the same time in two different threads (Android API Level 25).
I configured the SocketChannel as blocking mode.
For reading, I created an endless loop to read everything from server:
// Make socketChannel.read() return after 500ms at most
socketChannel.socket().setSoTimeout(500);
while(!SHUTDOWN) {
int read = socketChannel.read(buffer);
if(read > 0 ){
// Do something nice
break;
}
}
And for writing, I write data each 10 seconds.
The problem is, I found that sometimes the writing operations were blocked while reading.
But if I make the reading thread sleep for a short period in each loop, e.g. 100ms, this problem won't appear anymore.
looks like reading thread is blocking writing thread
AFAIK, TCP connections can offer bi-direction operations at the same time. Can anyone help to explain this?
As explained in TCP Wikipedia - Flow Control:
TCP uses an end-to-end flow control protocol to avoid having the
sender send data too fast for the TCP receiver to receive and process
it reliably. Having a mechanism for flow control is essential in an
environment where machines of diverse network speeds communicate. For
example, if a PC sends data to a smartphone that is slowly processing
received data, the smartphone must regulate the data flow so as not to
be overwhelmed.
I am using Mina2 with Camel to connect to a TCP server (over SSL).
Because Mina2 doesn't provide a default byte array decoder so I had to write a one on my own.
So, for some reasons, Mina splits the data received in chunks and calls the decode function multiple times and when I dug through the documentation, it says multiple threads could handle the received data and try to decode n number of times.
Here's the text:
MINA ensures that there will never be more than one thread simultaneously executing the decode() function for the same IoSession, but it does not guarantee that it will always be the same thread. Suppose the first piece of data is handled by thread-1 who decides it cannot yet decode, when the next piece of data arrives, it could be handled by another thread.
Now because I have a mina endpoint for I/O, camel maintains the same I/O session object for all transfers.
I am saving the decoder state using IOSession.setAttributes, say no. of bytes received so far for that particular exchange, and finish decoding when I receive the whole message.
My fear is that if there are two different exchanges going simultaneously and these different threads compete for the same IOSession property, the properties could get corrupt. I also can't seem to access the camel exchange property in Mina's decoder function, so I can't uniquely identify that particular exchange.
Any help in this regard would be great!!
A tcp socket is an endpoint which has bidirectional read and write capabilities. In java we can aquire InputStream and OutputStream of the Socket.
is it safe to use those streams concurrently?
As far as i know there is a single connection that is capable to send or recieve from one endpoint to other data at any given time.
I'm implementing nio transport layer based on SocketChannels, and i want to keep one thread for all writes and one thread for accepting and reads, but i'm not sure what will happen if my threads concurrently try to read and write at the same time on the same socket...
As far as I know there is a single connection that is capable to send or recieve from one endpoint to other data at any given time.
Or both at the same time. It's a full-duplex connection. You can send and receive at the same time.
I am developing a Net game, in general:
I have a server which launch a serverThread for each client that has connected to it.
Its purpose is to listen to messages from the specific client and to process it on the server.
Also for each client that is opened it launch a clientThread which is a listening thread to messages from the server.
The two threads are quite simple and similar threads which implements the Runnable Interface and therefore override the run method.
Each Run method is some kind of infinite loop that has on its start the command (blocking command):
int command = m_In.readInt();
and then do a process by switch cases structure over the received command.
after process was done, the loop cause the code to return to the blocking m_In.readInt()
To wait for another command to come.
My question is: My Net game has enough options which are using the communication over this m_In, so what happens if there are two messages or more coming almost together to the clientThread, how would the dataInputStream will act?
Will it begin to process first message and after its done will grab the second which is on some kind of a queue? or it could drop the second message and it will be lost?
Maybe that stream has buffer so it stores the second message in a queue or something?
Thanks
Streams by their nature expect data to come in a specified order. If you have two threads writing to the same stream at the same time, bad things will happen.
Now you can certainly synchronize access to the stream and have the two thread interleave their writing (so long as you build some sort of formatting on the stream that tells the receiver how to read data), but you don't get this by default.
Typically though, each client thread would have their own connection and thus their own stream to write into. A server can obviously read from multiple streams at the 'same time', and that is the normal server pattern.
my application has a queue with " outgoing network packets" (A POJO with a ByteBuffer and a SocketChannel) inside, consumed by a single thread that writes the data to the SocketChannel.
I do this to guarantee that every client that should receive packets, gets its turn. This means that SocketChannel.write() writes sequentially to multiple clients (= 1 at a time).
Can anyone tell me what could go wrong working like this? The SocketChannels are created from a ServerSocketChannel, so they're blocking.
I fear that the write() operation could block for 1 client, making the other clients wait...
The write() operation can indeed block in blocking mode. If you want fairness and single threading you will have to use non-blocking mode.
If a client socket fails to consume all the data in one write (non-blocking), you could close the client. This will only happen when the buffer fills, so you could increase the send buffer of the socket to a level where you are comfortable doing this.