android – java.net.BindException:绑定失败:EADDRINUSE(地址已在使用中)

我有一个服务,它启动Thread来对socket执行一些操作.代码如下:

 public class ServerRunnable implements Runnable {
    @Override
    public void run() {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket();
            serverSocket.setReuseAddress(true);
            serverSocket.bind(new InetSocketAddress(ProtocolConstants.USB_SERVER_PORT));
        while (true) {
            Socket client = serverSocket.accept();
            // some code
        } catch (Exception e) {
            Log.e("Exception while listening on socket.", e);
        } finally {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    Log.e(e);
                }
            }
        }

当我第一次启动服务时,一切正常,但是我必须使用stopService方法停止它.当我再次启动它时会返回以下异常:

java.net.BindException: bind failed: EADDRINUSE (Address already in use)

另外我在onDestroy服务方法中添加了ServerSocket,但它没有帮助.

setReuseAddress是在bind之前执行的,为什么它不起作用?

最佳答案
据我所知,它会卡在serverSocket.accept()上,等待连接进来.因此,即使关闭应用程序后,Runnable也永远不会完成.再次调用应用程序会出现此错误(因为该端口仍然被之前创建的Runnable阻止).有多种方法可以解决这个问题:

>您可以像这样调用和停止Runnable:

ThreadPoolExecutor threadPoolExecutor = Executors.newSingleThreadExecutor();
Runnable longRunningTask = new Runnable();
Future longRunningTaskFuture = threadPoolExecutor.submit(longRunningTask);
longRunningTaskFuture.cancel(true); //this might not trigger right away

>您可以通过调用serversocket.close()来停止serverSocket.accept()(这将抛出需要处理的SocketException)
>我通过我的Activity中的onClose()方法向我的serverSocket发送数据(字符串)来解决这个问题(可能不是正确的处理方法):

Socket socket = new Socket();
socket.setReuseAddress(true);
socket.connect((new InetSocketAddress(YOURSETTINGS, HERE);
OutputStream os = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(new String("TIMEOUT"));
oos.close();
os.close();
socket.close();

您可以选择在服务器中捕获此内容,如下所示:

ObjectInputStream objectInputStream = new objectInputStream(serverSocket.getInputStream());
Object object = objectInputStream.readObject();
if (object.getClass().equals(String.class) && ((String) object).equals("TIMEOUT"))
{
//Here you can do something with the Runnable before it is gone
}

转载注明原文:android – java.net.BindException:绑定失败:EADDRINUSE(地址已在使用中) - 代码日志