Java ServerSocket и Android LocalServerSocket - PullRequest
4 голосов
/ 04 ноября 2011

Я реализовал свой собственный сервис для Android следующим образом

public class MyService extends Service {
    private static final String TAG = "MyService";

    private Server mServer; 
    private LocalServerSocket server;

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        Log.d(TAG, "onCreate");
        mServer = new Server();
        mServer.start();
    }

    @Override
    public void onDestroy() {
        Log.d(TAG, "onDestroy");
        if(server != null){
            try {
                server.close();
            } catch (IOException e) {
                Log.d(TAG, "exception in server close");
                e.printStackTrace();
            }
        }
    }

    @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStart");
        return START_STICKY;
    }

    class Server extends Thread {
    @Override
        public void run() {
             try {
                server = new LocalServerSocket("my.socket");
                while (true) {
                    LocalSocket receiver;
                    try{
                        receiver = server.accept();
                    }catch(SocketException e){
                        Log.d(TAG, "SocketException");
                        break;
                    }
                    catch(IOException e){
                        Log.d(TAG, "IOException");
                        break;
                    }
                    if (receiver != null) {
                        Log.d(TAG, "Got Data in receiver");
                    }
                    receiver.close();
                }
            } catch (IOException e) {
                Log.d(TAG, "one more");
                e.printStackTrace();
            }
        }
    }
}

Проблема, с которой я сталкиваюсь, заключается в том, что если мой LocalServerSocket блокируется в accept (), то вызывается метод server.close () в OnDestroy.() не будет генерировать исключение SocketException.Следовательно, в следующий раз, когда я запускаю сервис, я получаю «адрес, который уже используется, исключение».Если вместо LocalServerSocket я использую java.net.Socket, то получаю требуемое поведение.Я хотел бы знать, почему LocalServerSocket ведет себя не так, как Java Sockets.В моем случае, как мне выйти из цикла while.

Ответы [ 2 ]

2 голосов
/ 17 июля 2013

У меня была такая же проблема, и я "решил" ее таким образом. Поток run () проверяет метод "! IsInterrupted ()". Метод stopSocketServer (), который я добавил в свой Listener-Thread, помечает поток для interrupt (), а затем отправляет запрос на подключение к себе, чтобы вызвать метод accept ().

/**
 * Executed if thread is started.
 */
public void run() {

    try {
        // leave while loop if thread is marked for interrupt.
        while (!isInterrupted()) { 
            LocalSocket clientSocket = serverSocket.accept();

            if (!isInterrupted()) {
                threadPool.execute(new ClientProcessor(clientSocket));
            }
        } 

    } catch (IOException e) {
        if (!isInterrupted()) {
            Log.e(TAG, "socket listener terminated", e);
        }
    } finally {
        try {
            if (serverSocket != null) {
                serverSocket.close();
            }
            if (threadPool != null) {
                threadPool.shutdownNow();
            }
            Log.i(TAG, "socket listener stopped");
        } catch (IOException e) {
        }
    }
} 

public void stopSocketServer() {
    if (serverSocket != null) {
        try {
            // mark thread as interrupted
            interrupt();

            // now send connect request to myself to trigger leaving accept()
            LocalSocket ls = new LocalSocket();
            ls.connect(serverSocket.getLocalSocketAddress());
            ls.close();
        } catch (IOException e) {
            Log.e(TAG, "stopSocketServer failed", e);
        }
    }
}
0 голосов
/ 04 ноября 2011

Из кода, который вы разместили, похоже, что ваш LocalServerSocket server останется null навсегда и onDestroy() не закроет его.Кроме того, закрытие сокета обычно не должно вызывать IOException - но accept() сделает это, если сокет закрыт одновременно.

...