Java ServerSocket 和 Android LocalServerSocket

发布于 2024-12-13 19:23:58 字数 2093 浏览 0 评论 0原文

我已经实现了我自己的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()中阻塞,那么在OnDestroy()中调用server.close()将不会抛出SocketException。因此,下次启动服务时,我会收到“地址已在使用异常”。如果我使用 java.net.Socket 而不是 LocalServerSocket,那么我会得到所需的行为。我想知道为什么 LocalServerSocket 的行为与 Java 套接字不同。就我而言,如何退出 while 循环。

I have implemented my own android service as follows

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();
            }
        }
    }
}

The problem I am facing is that, if my LocalServerSocket is blocking in accept(), then a call to server.close() in OnDestroy() will not throw a SocketException. Hence, next time I start the service, I get "address already in use exception". If instead of LocalServerSocket, I use java.net.Socket, then i get the required behavior. I would like to know why LocalServerSocket behaves differently from Java Sockets. In my case, how do I come out of the while loop.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

硬不硬你别怂 2024-12-20 19:23:58

我遇到了同样的问题并以这种方式“解决”了它。线程 run() 方法正在检查“!isInterrupted()”。我添加到监听线程的方法“stopSocketServer()”将线程标记为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);
        }
    }
}

I had the same problem and "solved" it this way. The thread run() method is checking for "!isInterrupted()". The method "stopSocketServer()" which I added to my Listener-Thread marks the thread for interrupt() and then made a connect request to itself to trigger the accept() method.

/**
 * 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);
        }
    }
}
命硬 2024-12-20 19:23:58

从您发布的代码来看,您的 LocalServerSocket 服务器 将永远保持 null 并且 onDestroy() 不会关闭它。另外,正常情况下关闭套接字不应抛出 IOException - 但如果同时关闭套接字,则 accept() 将会抛出异常。

From the code you've posted it looks like your LocalServerSocket server will remain null forever and onDestroy() won't close it. Also, closing the socket normally shouldn't throw IOException - but the accept() will do so if the socket is closed concurrently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文