比心跳包更优质的网络监听解决方案

一,提到客户端需要监听与服务器的连接是否断开首当其冲想到的时用心跳包解决,最近plc中控系统时最开始我也是通过发送紧急请求数据来达到心跳检查的效果,以往服务器对紧急状态码是默认不处理的,但是PLC确响应了该数据,由于plc没玩多久不好处理,故在前端进行改良。

二,改良方案:isusnpStream.read()是阻塞式方法,当socket的通信断开时此刻值为-1,那么就可以用-1来判断当前socket是否断开连接:方法如下贴上inputStream线程方法。

Thread threadIn = new Thread(new Runnable() {
    @Override
    public void run() {
        while (isClient) {
            Log.e("当前线程In:", Thread.currentThread() + "");
            try {
                int i = 0;
                in = client.getInputStream();
                byte[] bt = new byte[1024];
                while ((i = in.read(bt)) != -1) {
                    //input.read为阻塞io,读完当前数据会进入阻塞状态等待下一条数据,当断开时值为-1,跳出当前循环
                    str = new String(bt, 0, i);
                }
                //当in.read值为-1时,则视为与主机断开,此时关闭scoket以及输入输出流重新请求主机,并且跳出while循环
                netUtilScoket.safeClose(client);
                netUtilScoket.safeClose(in);
                netUtilScoket.safeClose(out);
                isClient = false;
            } catch (IOException e) {
                Log.e("socket连接断开", " Socket is closed" + e);
            }
        }
        openClientThread();//连接服务器scoket方法
    }l
});

这一步可以判断在通信过程中网络断开连接,下一步要解决的问题就是重连时如何判断是否重连成功,也包括初始化连接时是否连接成功的判断,在这里有一点大家需要注意很多兄弟都会以为socket.setSotimeout(5000)方法时用来设置socket的连接超时的,事实上这并不是而是数据接受的超时时间设置,所以不要用该方法的时间来判断是否连接成功,socket=new socket(ip,port);会强制加上try cath 方法,当出现异常时则视为没有连接成功,此刻可以尝试进行第二次socket连接,这样和心跳包定时连接服务器的好处在哪里呢?如果心跳包时间间隔太短,会导致前面几次连接并没失败的情况下你进行了成功的连接,这样一次性会给socketServe端瞬间增加好几个连接对象。下面贴下连接代码:

 /**
     * @effect 开启线程建立连接开启客户端
     */
    public void openClientThread() {
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    /**
                     *  connect()步骤
                     * */
                    client = new Socket(site, port);
                    client.setSoTimeout(0);
                    if (client != null) {
                     //连接成功
                        isClient = true;
                        forOut();//初始化输出流
                        forIn();//开启输入流线程
                    } else {
                        isClient = false;
                        Looper.prepare();
                        Toast.makeText(context, "网络连接失败", Toast.LENGTH_LONG).show();
                        Looper.loop();
                    }
                } catch (UnknownHostException e) {
                    e.printStackTrace()
                } catch (IOException e) {
                    netUtilScoket.safeClose(client);
                    netUtilScoket.safeClose(in);
                    netUtilScoket.safeClose(out);
                    e.printStackTrace();
                    //连接时失败,重新连接
                    openClientThread();
                }

            }
        });
       //线程池控制
        defaultThreadPool().execute(thread);
    }

三,当然各种监听方法各有取舍,这里只是提供一个实现思路,希望能大家提供一点帮助。

你可能感兴趣的:(android)