1

我已经构建了一个连接到 Ip、发送hello world并定期发送日期时间的小型 android 测试 tcp 客户端。

为了测试这一点,我使用netcat作为服务器,方式如下:

nc -l 5000

客户端通过套接字连接到服务器,并且使用 wifi 或 3g 网络在netcat屏幕上正确显示日期时间。

如果在 3g 中启动应用程序并让应用程序在一小段时间(一秒间隔)内发送日期时间并更改为 wifi 网络,我将获得EHOSTUNREACH用于由 tcp 客户端应用程序或任何其他连接到我的服务器 IP 的所有连接任何端口(例如浏览器)上的应用程序,但仅限于发生错误的 wifi 网络中。

如果我更改为 3g 或另一个 wifi 网络,则不会返回错误,但如果我回到那个 wifi 网络,我会再次收到错误。并保持这种状态,直到我重新启动手机或将 android 单独放置约 30 分钟。

这仅在某些网络中发生,并且仅在数据发送周期很小的情况下,每次更改时都会发生 1 秒或更短的间隔,如果周期为 5 秒,则每 4-5 次更改发生 1 次。

客户端代码如下

    private void test(){
    AsyncTask<Void,Void,Void> task = new AsyncTask<Void,Void,Void>(){

        @Override
        protected Void doInBackground(Void... params) {
            int iterador = 0;
            try {
                if(mSocket!= null && !mSocket.isClosed()){
                    mSocket.close();
                }

                if(waitNetworkConnection(getApplicationContext(), 3))
                {

                    mSocket = new Socket(Proxy.NO_PROXY);
                    mSocket.setReuseAddress(false);
                    mSocket.setSoTimeout(100);
                    mSocket.setTcpNoDelay(false);//false seems to work better
                    mSocket.setKeepAlive(false);
                    mSocket.setSoLinger(false, 5);
                    mSocket.setOOBInline(false);



                    mSocket.connect(new InetSocketAddress("xxx.xxx.xxx", 5000));



                    PrintWriter out;
                    OutputStream stream = mSocket.getOutputStream();
                    OutputStreamWriter outputStream = new OutputStreamWriter(stream);
                    BufferedWriter buff = new BufferedWriter(outputStream);
                    out = new PrintWriter(buff, true);  
                    out.println("hello");
                    out.println("world");

                    Date date;
                    do {
                        try {
                            Thread.sleep(200);

                            if(out.checkError() || mSocket.isOutputShutdown())
                            {
                                System.out.println("some error has happed let's close the socket");


                                try {
                                    mSocket.shutdownOutput();
                                }
                                catch(Exception e){}
                                try {
                                    mSocket.shutdownInput();
                                }
                                catch(Exception e){}
                                try {
                                    mSocket.close();
                                }
                                catch(Exception e){}

                            }else
                            {
                                if(waitNetworkConnection(getApplicationContext(), 3))
                                {
                                    if(iterador > 10*5)
                                    {
                                        Thread.sleep(5000);
                                    }
                                    date = new Date();
                                    String msg = "["+String.valueOf(iterador)+"] keeping connection at "+date.toString();
                                    System.out.println("Sending: " + msg);
                                    out.println(msg);

                                    out.flush();
                                    iterador++;
                                }
                            }
                        } catch (InterruptedException e) {

                            e.printStackTrace();
                        }

                    }while(!mSocket.isClosed());

                }
            }
            catch(Exception se){
                String err = se.getMessage();
                if(null == err){
                    err = se.toString();
                }
                System.out.println(err);
            }
            System.out.println("Socket closed");

            new Handler(getMainLooper()).postDelayed(new Runnable() {

                @Override
                public void run() {

                    test();
                }
            }, 5000);

            return null;
        }

    };
    task.execute();
}
public static boolean waitNetworkConnection(Context context, int retries) throws InterruptedException {
    ConnectivityManager cm = (ConnectivityManager) 
            context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo ni = getNetworkToTest(cm);

    if (ni == null || !ni.isConnected()) {
        // sleep a short while to allow system to switch connecting networks.
        Thread.sleep(1000);
        int counter = 0;
        while (counter < retries && (ni == null || (ni.isAvailable() && 
                !ni.isConnected()))) {
            Thread.sleep(500);
            ni = getNetworkToTest(cm);
            counter++;
        }
    }

    return (cm.getActiveNetworkInfo() != null && 
            cm.getActiveNetworkInfo().isConnected());
}

private static NetworkInfo getNetworkToTest(ConnectivityManager cm) {
    NetworkInfo[] nis = cm.getAllNetworkInfo();
    NetworkInfo ni = cm.getActiveNetworkInfo();

    for (int i = 0; i < nis.length; i++) {
        if (nis[i].getType() == ConnectivityManager.TYPE_WIFI && nis[i].isAvailable()) {
            ni = nis[i];
            return(ni);
        }
    }
    return(ni);
}

这个测试是在三星 Galaxy S3 (android 4.1.2) 和三星 Galaxy S2 (android 4.1.2) 上进行的。发生这种情况的路由器的一个网络是 D-link 802.11g/2.4GHz

4

0 回答 0