1

Ip に接続し、hello worldを送信し、定期的に datetime を送信する小さな Android テスト tcp クライアントを作成しました。

これをテストするために、次の方法でnetcatをサーバーとして使用しています。

nc -l 5000

クライアントはソケットを介してサーバーに接続し、wifi または 3g ネットワークを使用してnetcat画面に datetime が正しく表示されます。

アプリを 3g で起動し、アプリから日時を送信したまましばらくの間 (1 秒間隔)、Wi-Fi ネットワークに変更すると、サーバー IP へのすべての接続に対してEHOSTUNREACHが取得され、TCP クライアント アプリまたはその他のアプリによって作成されます。 app を任意のポート (ブラウザなど) で使用できますが、エラーが発生した Wi-Fi ネットワークでのみ使用できます。

3g または別の Wi-Fi ネットワークに変更すると、エラーは返されませんが、その Wi-Fi ネットワークに戻ると、再度エラーが発生します。そして、電話を再起動するか、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);
}

これは、Samsumg galaxy S3 (android 4.1.2) および Samsung Galaxy S2 (android 4.1.2) で行われたテストです。ルーターでこれが発生するネットワークの 1 つは、D リンク 802.11g/2.4GHz です。

4

0 に答える 0