2

In my application I am using TCP socket connection to connect android device to server. Socket is working normally on every device, except devices with Android 7+ where I get "Socket is closed" error. Socket problems happen on Nexus 6P and Samsung s7!

I am using socket in Runnable in a Service, initializing socket with:

public class ClientThread implements Runnable {

    public void run() {
        while (true) {
            try {
                DataHandler.indicator.set(false);
                mRun = true;
                if (DataHandler.DOMAIN_IP.contains(":")) {
                    serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.split(":")[0]);
                } else
                    serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.replace(":3030", ""));
                Log.i("Socket", "Connecting");
                socket = new Socket(serverAddr, SERVERPORT);
                socket.setKeepAlive(true);
                socket.setSoLinger(true, 1);
                socket.setSoTimeout(30000);
                DataHandler.IP_ADDRESS = socket.getLocalAddress().toString().split("/")[1];
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                connectionDelay = MIN_WAIT;
                Log.i("Socket", "Connected");
                String serverMessage = "";
                byte[] array = new byte[1024];
                while (mRun) {
                    int firstbye = dis.read();
                    int arraylength = dis.available();
                    array = new byte[arraylength];
                    dis.read(array, 0, array.length);
                    String str = new String(new byte[]{(byte) firstbye});
                    serverMessage += str + EncodingUtils.getString(array, "UTF-8");
                    DataHandler.indicator.set(true);
                    if (firstbye != -1) {
                        String mstString = new String(serverMessage);
                        serverMessage = "";
                        onReceive(NotificationService.this, mstString);
                    } else { // if (serverMessage.equalsIgnoreCase("")) {
                        try {
                            socket.close();
                            Log.e("Socket", "Disconnect");
                            socket = null;
                            stopClient();
                        } catch (Exception e) {
                            e.getMessage();
                        }
                        serverMessage = null;
                        DataHandler.indicator.set(false);
                        continue;

                    }
                }
            } catch (UnknownHostException e) {
                isNeedtoWrite = true;
            } catch (IOException e1) {
                isNeedtoWrite = true;
                DataHandler.indicator.set(false);
            } finally {
                try {
                    socket.close();
                    DataHandler.indicator.set(false);
                    Log.e("Socket", "Disconnect");
                    socket = null;
                    stopClient();
                } catch (Exception e) {
                    e.getMessage();
                }
            }
            try {
                connectionDelay = Math.min(MAX_WAIT, RandomUtils.nextInt(MIN_WAIT, (int) (connectionDelay * BACKOFF_RATE)));
                Log.i("SocketSleep", String.valueOf(connectionDelay));
                Thread.sleep(connectionDelay);
                DataHandler.indicator.set(false);
            } catch (InterruptedException e) {
                e.getMessage();
            }
        }
    }
}

Before code reaches setSoTimeout it gets to exception.

I have tried a different application which uses same Socket logic and on start it worked normally and then it just dropped unexpectedly and it doesn't work anymore. I checked on wireshark and this happens:

Wireshark

Does anyone have any clue what could the problem be?

Tomek
  • 557
  • 2
  • 7
  • 24

3 Answers3

1

Bux fix:

Due to a bug in previous versions of Android, the system did not flag writing to a TCP socket on the main thread as a strict-mode violation. Android 7.0 fixes this bug. Apps that exhibit this behavior now throw an android.os.NetworkOnMainThreadException. Generally, performing network operations on the main thread is a bad idea because these operations usually have a high latency that causes ANRs and jank.

And link to documentation.

Domen Jakofčič
  • 626
  • 1
  • 8
  • 24
  • This is not the issue. I am running Runnable with "new Thread(new ClientThread())" so it uses a different thread, and I have tried putting the code to AsyncTask inBackground, and result is the same – Tomek Feb 03 '17 at 14:21
  • I see you are using DateHandler, I don't konw exactly for what it is or anything, but maybe your handler using Looper.getMainLooper() which use main thread? I'm just guessing. – Domen Jakofčič Feb 03 '17 at 14:34
  • DataHandler is only for static variables in this case public static AtomicBoolean indicator = new AtomicBoolean(false); – Tomek Feb 03 '17 at 15:00
  • Are you able to fix this issue. I am also facing the same issue – Jaffar Raza May 08 '17 at 06:56
0

I found out what the problem was... I actually HAD some code which called

socket.getOutputStream().write(GetSendString());

outside my thread, and this was causing socket to disconnect / crash because of NetworkOnMainthread error, but I didn't have Exception handled properly!

Tomek
  • 557
  • 2
  • 7
  • 24
-2

Maybe the problem is caused by reading the InputStream using .read command. Try using BufferedReader, and similar for the OutputStream :

BufferedReader dis =  new BufferedReader(
                                new InputStreamReader( socket.getInputStream() ));

PrintWriter os_buffer = new PrintWriter(
                                new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
trunks0
  • 11
  • 2