views:

30

answers:

1

Hey all, I'm using a UNIX socket to facilitate communication on and Android device between a system level daemon I've got running in C and an application I've got running in Java. I'm much more of a C coder than a Java coder, so I'm having some issues when trying to read in data from the socket on the Java side. Currently, my code is as follows:

try{//Prepare to write the command and read the ACK
  InputStream is = receiver.getInputStream();
  OutputStream os = receiver.getOutputStream();
  BufferedReader in = new BufferedReader(new InputStreamReader(is));

  os.write(message.getBytes());

  //FIX THIS!!  The following assumes that there is a newline-
  //  terminated chunk of data waiting for us in the buffer.  If
  //  that assumption is wrong, the code will hang.  Find some way
  //  to determine if/how much data is waiting for us in the socket!
  String str = in.readLine();

  is.close();
  os.close();
  receiver.close();
     return str;
 }catch(IOException ex){
  Log.e(TAG,(ex.toString()+"\n"));
  return null;
 }

As my comment indicates, this implementation works(ish), but has the very bad design flaw of requiring that the server side socket code responds with a newline terminated string. If that's not the case, the world ends.

What I'm trying to figure out is if there is a better means of accomplishing this task. Is it possible to determine if there is any data waiting to be read in a buffered reader, and if so, what the size of that data is? If not, is there a better way of reading in data over a UNIX socket on the Java side of Android that I'm not familiar with?

Thanks in advance!

A: 

if the protocol requires a newline, your impl is appropriate. the code SHOULD be blocked until a newline is read. what else can you do but wait?

of course, usually you don't want to wait forever, you need a timeout. see Socket.setSoTimeout()

if a newline is not necessarily given by server, and you just want to read any data as soon as available, use InputStream.read()

irreputable
Thanks!Another thing I was curious about- I just noticed the available() function of the InputStream class. Combining that with read() gives mewhile(is.available() != 0) str += (char)is.read();return str;This seems to work, but the word "estimated" in the description of available() has me a bit leery- how dependable is available()?
Jordan Wills
available()==0 doesn't mean end of stream. read()==-1 does mean that. you will not likely need available().
irreputable
are you certain that read() == -1 is end of stream for a UNIX socket? my current snippet isint readByte = is.read();while(readByte != -1) { str += (char)readByte; readByte = is.read();}but this seems to timeout before -1 is read. At least, I'm assuming it is timing out- what actually happens is that my application clean crashes back to the home screen, and log cat vomits output all over the place. Specifically, it throws an exception off a JNI method that LocalSocket is calling, followed by a huge stack trace, Dalvik aborting, and a slew of memory address mapping information.
Jordan Wills
bwar, and sorry for the sloppy formatting- still new to stack overflow, and I haven't gotten the hang of formatting code in comments yet
Jordan Wills
timeout could come before end of stream. other exceptions can also occur. you can `try-catch` exceptions and decide what to do with them.
irreputable
Currently, I have that block of code surrounded in a try statement to catch IO exceptions, but still no dice. I'm confused as to why is.available() > 0 is working for my while condition, but is.read() != -1 is never being met. What are the conditions under which a socket will transmit an end of stream character? Is that something I need to manually send from the server I've got coded in C? It is my (admittedly novice) understanding that end of stream is only sent over a unix socket when the socket connection is closed- is that incorrect?
Jordan Wills
if the server closes the connection, the client will read a -1. that's one way to signal the end of message. you can also design your protocols to include some message delimiters, so that once the client read a delimiter, it knows it has one complete message.
irreputable