Reputation: 35
I am creating some client-side socket software to read events from a server. (For example, streaming stock quotes).
PROBLEM: .read(b); is returning immediately with a value of -1. This causes an infinte loop and the phone becomes very hot. Additionally, all checks to s.isConnected(), isOpen(), isBound() return true. Essentially the socket looks connected. (This is an error scenario, so any value of .setSoTimeout(x) has no effect. 12 minutes, or leave empty. The .read(b) always returns -1 immediately).
When I write to it later, via the getOutputStream(), I receive an exception EPIPE (broken pipe).
Here's the core code (log statements/value checks omitted for brevity).
s.connect(new InetSocketAddress(host, port), CONNECT_TIMEOUT_MILLIS);
byte[] b = new byte[1024];
while (s.isConnected()) {
int bytesToRead = s.getInputStream().read(b);
if (bytesToRead <= 0) {
LOGGER.debug("no bytes read? trying again.");
continue;
}
processFrame(b);
}
If I cycle the 3g on the phone, it works fine. Sometimes it gets into this weird state.
Question
Am I doing something wrong? Is this the expected behavior? Is there existing code I could look at to show the right way to do socket programming on Android?
Upvotes: 1
Views: 11895
Reputation: 310893
If read(byte[], ...)
returns < 0, the peer has closed the connection, so you must close the socket and exit the loop. There will never be any more data.
Input streams are blocking, so the only way read(byte[], ...)
can return zero is if you specify a zero length buffer or a zero length, depending on which overload you call. As you aren't doing that, it will never return zero.
Instead it will do exactly what it says in the Javadoc: either return -1 meaning EOS, or block until at least one byte of data is available.
Am I doing something wrong?
Almost everything. Your loop testing for <= 0
is completely pointless and completely incorrect. And so is testing isConnected()
. That only tells you whether you ever connected this Socket
. It doesn't change with the state of the connection. The return code of -1 tells you that. Your loop should read:
while ((bytesToRead = s.getInputStream().read(b)) > 0)
{
// do something with b[0..bytesToRead -1].
}
s.close();
Upvotes: 2
Reputation: 33534
Well i don't know whether this would be the appropriate answer for this, but still i will like to give you the code, which does works well every time.
Please keep it simple,
Try using InputStream, InputStreamReader, BufferedReader, OutputStream, PrintWriter.
Client Side:
Socket s = new Socket();
s.connect(new InetSocketAddress("Server_IP",Port_no),TimeOut);
// Let Timeout be 5000
Server Side:
ServerSocket ss = new ServerSocket(Port_no);
Socket incoming = ss.accept();
For Reading from the Socket:
InputStream is = s.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
boolean isDone = false;
String s = new String();
while(!isDone && ((s=br.readLine())!=null)){
System.out.println(s); // Printing on Console
}
For Writing to the Socket:
OutputStream os = s.getOuptStream();
PrintWriter pw = new PrintWriter(os)
pw.println("Hello");
Upvotes: 0
Reputation: 12048
I use the following code without problem:
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
myLineProcess(line); //here you process you line result
}
good luck.
Upvotes: 3