Edit: I’ve found the problem ( see answer below )
I’m trying to write an Android application to send data to a running termux
instance via TCP.
In termux, I have netcat listening for incoming TCP connections and printing data to stdout
using the command nc -l localhost 8080
.
In my android app, I have a thread that reads in strings from a blocking queue and writes them out to a socket connectd to the address that netcat is listening on. The relevant code is the following:
runnable = () -> { Socket socket = null; OutputStream socketOutStream = null; while (running) { try { if (null==socket) { socket = new Socket(); socket.setTcpNoDelay(true); socket.setKeepAlive(true); socket.connect(new InetSocketAddress("127.0.0.1", 8080), 2000); socketOutStream = socket.getOutputStream(); socketOutStream.write("Hello, Server!".getBytes()); // [1] Works!! socketOutStream.flush(); } String message = queue.take(); socketOutStream.write(message.getBytes()); // [2] Doesn't work!!? socketOutStream.flush(); socketOutStream.close(); Log.i(TAG, "We wrote 'Button Clicked!' to the socket I think."); // running=false; } catch (IOException e) { Log.e(TAG, e.toString()); socket = null; } catch (InterruptedException e) { Log.e(TAG, e.toString()); Log.i(TAG, "Exiting socket sending loop."); running = false; } } }; Thread thread = new Thread(runnable); thread.start();
I’m trying to figure out why the initial data sent to netcat at the line marked [1]
is actually received and displayed inside termux, but any subsequent data sent at [2]
is not. The incoming strings fetched from the queue are certainly not empty.
Additionally, if I move the socket instantiation and connection logic to occurr until after queue.take()
returns, I see a SocketTimeoutException
via adb log output.
I would like to understand why it should make any difference whether either of these operations shoud occurr before or after the queue.take()
operation returns.
Advertisement
Answer
I was eventually able to resolve the issue with the TCP socket hanging by attaching the socket to a foreground service as opposed to a background service which is how it was running in the first instance. It seems Android background services are liable to have TCP communications delayed or buffered in order to economize battery usage.