I'm trying to pipe some ByteBuffer in a thread (IO1) to another (IO2).
http://tutorials.jenkov.com/java-nio/pipe.html
private int bufferSize;
private boolean isRecording;
private Thread IO1;
private Thread IO2;
private ByteBuffer byteBuffer1;
private ByteBuffer byteBuffer2;
private Pipe pipe;
private Pipe.SinkChannel skChannel;
private Pipe.SourceChannel sourceChannel;
byteBuffer1 = ByteBuffer.allocateDirect(bufferSize);
byteBuffer2 = ByteBuffer.allocateDirect(bufferSize);
//An instance of Pipe is created
try
{
pipe = Pipe.open();
skChannel = pipe.sink();
sourceChannel = pipe.source();
IO1.start();
IO2.start();
}
catch (IOException e)
{
e.printStackTrace();
}
--
IO1 = new Thread(new Runnable()
{
public void run()
{
isRecording = true;
recorder.startRecording();
try
{
int read;
while (isRecording)
{
// byteBuffer1.clear();
read = recorder.read(byteBuffer1, bufferSize);
if (AudioRecord.ERROR_INVALID_OPERATION != read)
{
skChannel.write(byteBuffer1);
Log.v("========IO1 ", String.valueOf(read));
//This triggered almost 20 times/second
}
}
recorder.stop();
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
skChannel.write(byteBuffer1); and
Log.v("========IO1 ", String.valueOf(read));
is triggered almost 20 times/second, and this is the expected behavior, so far so good.
IO2 = new Thread(new Runnable()
{
public void run()
{
try
{
int read;
while ( (read =sourceChannel.read(byteBuffer2)) >0)
{
Log.v("========IO2 ", String.valueOf(read));
//this triggered only once
// To do Codec etc.
//............
}
}
catch (IOException e)
{
e.printStackTrace();
}
Log.v("========IO2 ", "END!!!!!"); //never triggered(this is fine)
}
});
However, Log.v("========IO2 ", String.valueOf(read)); is triggered only once, and I don't know why.
Can someone tell me how can I obtain the update of Thread IO1 in IO2?
Thanks.
You need to flip() the buffer before writing, and compact() it afterwards.
BUT: In a word, don't. Pipes between threads are basically pointless. Use a queue, or have the receiving thread read the sending thread's input directly.
If you must do this, the basic NIO copy loop goes like this:
while (in.read(buffer) > 0 || buffer.position() > 0) // or whatever your read API needs
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
Related
I've created a code that reads data thrown to my android device from an Arduino. It goes like this:
public void run() {
byte[] buffer = new byte[1024];
int bytes;
final StringBuilder readMessage = new StringBuilder();
while (true) {
try {
bytes = connectedInputStream.read(buffer);
final String string_now = new String(buffer, 0, bytes);
readMessage.append(string_now);
// final int finalBytes = bytes;
runOnUiThread(new Runnable() {
#Override
public void run() {
tvBPM.setText(string_now);
readMessage.setLength(0);
}
});
} catch (IOException e) {
Toast.makeText(getApplicationContext(),"Connection Lost!",Toast.LENGTH_LONG).show();
}
}
}
This code is located inside my 'private class ThreadConnected extends Thread'
Now the values held by string_now are numbers. I want to tell the user if the value stored there is greater than 150 or less than 50. Here's a code I've tried but I doesn't fully work.
runOnUiThread(new Runnable() {
#Override
public void run() {
final int getValue = Integer.getValue(Integer.parseInt(string_now));
if (getValue > 150 || getValue < 50) {
Toast.makeText(getApplicationContext, "Unstable", Toast.LENGTH_SHORT).show(); }
else {
tvBPM.setText(string_now);
readMessage.setLength(0); }
}
});
Any tips on how I can make this work? Thank you.
bytes = connectedInputStream.read(buffer);
final String string_now = new String(buffer, 0, bytes);
This code will run forever even after the peer closes the connection, when it will start showing rubbish, giving ArrayIndexOutOfBoundsException, or whatever. You are missing the following between those two lines:
if (bytes == -1)
{
break;
}
and the following after the catch block:
finally
{
try
{
connectedInputStream.close();
}
catch (IOException exc)
{
// whatever ...
}
}
My project used JSSC library for linking PC and microcontroller.
Write method:
public void write(byte[] buffer) throws SerialPortException {
if (serialPort.isOpened())
serialPort.writeBytes(buffer);
}
Read method:
public byte[] read() throws SerialPortException {
byte[] result = null;
FutureTask<byte[]> task = new FutureTask<>(new PortReader());
ExecutorService executor = Executors.newSingleThreadExecutor();
try {
result = (byte[]) executor.submit(task).get(1000, TimeUnit.MILLISECONDS);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
System.err.println(getClass().getSimpleName() + " READ: Timeout exception!");
}
return result;
}
private class PortReader implements Callable<byte[]>, SerialPortEventListener {
private byte[] data = null;
#Override
public void serialEvent(SerialPortEvent event) {
if (event.isRXCHAR() && event.getEventValue() > 0) {
try {
data = serialPort.readBytes(event.getEventValue());
} catch (SerialPortException e) {
e.printStackTrace();
}
}
}
#Override
public byte[] call() throws Exception {
if (data == null)
Thread.sleep(200);
return data;
}
}
I tried to implement a synchronous write (immediately send data) to the port and asynchronous read (waiting for the input data at least 1000 ms) from port.
Is it correct decision? Maybe there are other ways of asynchronous data reading?
Thank you!
Better to use the wait event as used inside serialport class. This way makes the port to wait until a command is equecuted.
serialPort.writeBytes(buffer);//Write data to port
serialPort.addEventListener(new PortReader(serialPort), SerialPort.MASK_RXCHAR);
int[][] eventArray=serialPort.waitEvents()
for (int i = 0; i < eventArray.length; i++) {
if ((eventArray[i][0] > 0) ) {
serialPort.eventListener.serialEvent(new SerialPortEvent("COM1", eventArray[i][0], eventArray[i][1])); //give your port name and the events got.
}
}
I would like to test the connection between a client and a server in a ScheduledExecutorService every x ms while processing received data from the distant host.
So I did something like this:
public class MyClass {
private final ScheduledExecutorService _timer = Executors.newScheduledThreadPool(1);
private Socket _connection;
public void connectToDistantHost() {
try {
_connection = new Socket();
_connection.connect(_adresseServeur);
new Thread(new Runnable() {
#Override
public void run() {
try {
//let another object know the connection is ok
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
_timer.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
testConnection();
}
}, 0, 200, TimeUnit.MILLISECONDS);
}
private void testConnection() {
//would like to peek on the socket's inputstream to know if something's wrong
}
private void myProcessing() {
while (true) {
...
//read what's inside stream
//process it in a thread
}
}
}
So, if I .read() on the Socket's inputstream it'll screw myProcessing(). I thought about wraping the inputstream in a BufferedReader and mark the buffer position before I read and then reset the position, but as the testing and the processing are in two differents thread it won't work anyway.
How can I do that? Knowing that I did it in c# without much problem:
class TraitementEnvoiClient {
...
private void testConnection(Object obj, ElapsedEventArgs args) {
_connectionIsOk = _connexionAuServeur.IsConnected();
if (!_connectionIsOk) {
tryToReconnect();
}
}
}
public static class ExtensionTcpClient {
//Credit to ElFenix: http://social.msdn.microsoft.com/Forums/en-US/c857cad5-2eb6-4b6c-b0b5-7f4ce320c5cd/c-how-to-determine-if-a-tcpclient-has-been-disconnected?forum=netfxnetcom
public static bool IsConnected(this TcpClient client) {
// Detect if client disconnected
try {
if (client.Client.Poll(0, SelectMode.SelectRead)) {
byte[] buff = new byte[1];
if (client.Client.Receive(buff, SocketFlags.Peek) == 0) {
// Client disconnected
return false;
}
}
} catch (SocketException se) {
return false;
}
return true;
}
}
Thank you
Edit: I would like to make something like that:
private static boolean isConnected(Socket client) {
try {
InputStream is = client.getInputStream();
if(is.peek() == -1) return false;
OutputStream os = client.getOutputStream();
os.write(new byte[]{}); //if it fails a IOException will trigger
} catch(SocketException se) {
return false;
} catch(IOException ioe) {
return false;
}
return true;
}
The testing is redundant. The read or write operations will return -1 if the other end closes or disconnects before or during the operation. There is no point in "testing" the connection first because it may subsequently fail during your IO operation.
See also the other answer mentioned in the comments.
Under what circumstances read end can be dead in couple PipedOutputStream and PipedInputStream? I am not closing any pipes.
I encountered java.io.IOException: Read end dead in my code and found out the cause. Posting an example code below. You will get an "Read end dead" exception if you run the code. If you take a close look, the consumer thread reads "hello" from the stream and terminates; meanwhile the producer sleeps for 2 seconds and tries to write " world" but fails. A related problem explained here: http://techtavern.wordpress.com/2008/07/16/whats-this-ioexception-write-end-dead/
class ReadEnd {
public static void main(String[] args) {
final PipedInputStream in = new PipedInputStream();
new Thread(new Runnable() { //consumer
#Override
public void run() {
try {
byte[] tmp = new byte[1024];
while (in.available() > 0) { // only once...
int i = in.read(tmp, 0, 1024);
if (i < 0)
break;
System.out.print(new String(tmp, 0, i));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}).start();
PipedOutputStream out = null;
try {
out = new PipedOutputStream(in);
out.write("hello".getBytes());
Thread.sleep(2 * 1000);
out.write(" world".getBytes()); //Exception thrown here
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
}
}
}
I have the following code, i want to be able to restart the thread if an exception occurred while processing a request.
The following in the run method of a thread:
int status = httpConn.getResponseCode();
if (status == HttpConnection.HTTP_OK) {
// Is this html?
String contentType = httpConn
.getHeaderField(HEADER_CONTENTTYPE);
boolean htmlContent = (contentType != null && contentType
.startsWith(CONTENTTYPE_TEXTHTML));
InputStream input = s.openInputStream();
byte[] data = new byte[1000];
int len = 0;
int size = 0;
StringBuffer raw = new StringBuffer();
while (-1 != (len = input.read(data))) {
// Exit condition for the thread. An
// IOException
// is
// thrown because of the call to
// httpConn.close(),
// causing the thread to terminate.
if (_stop) {
httpConn.close();
s.close();
input.close();
}
raw.append(new String(data, 0, len));
size += len;
}
// raw.insert(0, "bytes received]\n");
// raw.insert(0, size);
// raw.insert(0, '[');
content = raw.toString();
if (htmlContent) {
content = prepareData(raw.toString());
}
input.close();
} else {
try{
httpConn.close();
}catch (Exception e) {
// TODO: handle exception
}
errorDialog(status+", status code");
retryFeed(getUrl(), "Network error. Retrying...");
}
s.close();
} else {
errorDialog("Sorry Insufficient Network Coverage.");
return;
}
} catch (IOCancelledException e) {
errorDialog(e.getMessage());
retryFeed(getUrl(), "Network error. Retrying...");
} catch (IOException e) {
errorDialog(e.getMessage());
retryFeed(getUrl(), "Network error. Retrying...");
}
What is the safest way to retry the connection if failed?
Thanks.
//New This is the Error thread. That check for errors in the connection... will this help? and is it the most efficient method? thanks..
/Error Thread - Thread to check errors/
private class ErrorThread extends Thread {
private static final int TIMEOUT = 3000; // EVERY 3 Seconds
private boolean hasException = false;
private String _theUrl;
/**
* Stops this thread from listening for messages
*/
private synchronized void stop()
{
hasException =false;
}
/**
* Listens for incoming messages until stop() is called
* #see #stop()
* #see java.lang.Runnable#run()
*/
public void run()
{
try
{
while (true) {
if((hasException==true))
{
// Synchronize here so that we don't end up creating a connection that is never closed.
errorDialog("Will Fetch new");
synchronized(this)
{
hasException=false;
if (!_connectionThread.isStarted()) {
fetchPage(_theUrl);
} else {
createNewFetch(_theUrl);
}
}
}
try {
//errorDialog("No exception.");
sleep(TIMEOUT);
} catch (InterruptedException e)
{
errorDialog("Exceptions"+e.toString()+e.getMessage());
System.exit(1);
//System.exit(0);/*Kill System*/
}
}
}
catch (Exception except)
{
}
}
public void setActive(boolean exception,String url)
{
this.hasException=exception;
this._theUrl=url;
}
}
If the connecrtion fails, typically, you want to close it, pause a small time, and retry. The purpose of the pause is to prevent your device from devoting excessive resources to trying to connect to a server that's having issues.