TCP套接字无法在Android 7+设备上运行

时间:2017-02-03 12:39:55

标签: java android sockets tcp

在我的应用程序中,我使用TCP套接字连接将android设备连接到服务器。 Socket在每台设备上正常工作,除了安装了Android 7+的设备,我收到“Socket is closed”错误。 Nexus 6P和三星s7上出现套接字问题!

我在Service中的Runnable中使用socket,使用:

初始化套接字
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();
            }
        }
    }
}

在代码到达setSoTimeout之前,它会变为异常。

我尝试了一个使用相同Socket逻辑的不同应用程序,并且在启动时它正常工作然后它意外地掉线并且它不再起作用了。我查看了wireshark,这种情况发生了:

Wireshark

有没有人知道问题是什么?

3 个答案:

答案 0 :(得分:1)

Bux修复:

  

由于以前版本的Android中存在错误,系统没有将主线程上的TCP套接字标记为严格模式违规。 Android 7.0修复了这个bug。出现此行为的应用程序现在抛出android.os.NetworkOnMainThreadException。通常,在主线程上执行网络操作是一个坏主意,因为这些操作通常具有导致ANR和jank的高延迟。

并链接到documentation

答案 1 :(得分:0)

我发现问题是什么......我实际上有一些叫做

的代码
socket.getOutputStream().write(GetSendString());

在我的线程之外,由于NetworkOnMainthread错误导致socket断开/崩溃,但我没有正确处理Exception!

答案 2 :(得分:-2)

使用 .read 命令阅读 InputStream 可能会导致问题。 尝试使用 BufferedReader ,类似于 OutputStream

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

PrintWriter os_buffer = new PrintWriter(
                                new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);