当我重新启动应用程序时,我遇到了BindException。它充当等待远程控制消息的服务器。 ServerSocket在后台线程(AsyncTask)中运行。重启我的应用程序后,我总是得到上面提到的例外。我必须等待10分钟,直到它再次绑定到端口才能收听。
我尝试了不同的端口(全部> 50000),所以我确定没有其他应用程序阻止我的端口。关于关闭套接字我试图小心,我试图使用SO_REUSEADDR选项。此外,我确信在运行时只有一个连接打开,因为我记录了每个socketbind。
所以我认为,连接没有正确关闭。我已经读过关于插座没有立即关闭的习惯。但我不能等待每次重启应用程序10分钟,我没有找到缩短或杀死此时间的方法。
你有什么想法吗?
例外:
10-04 16:39:22.526: WARN/System.err(4974): java.net.BindException: Address already in use
10-04 16:39:22.526: WARN/System.err(4974): at org.apache.harmony.luni.platform.OSNetworkSystem.bind(Native Method)
10-04 16:39:22.526: WARN/System.err(4974): at dalvik.system.BlockGuard$WrappedNetworkSystem.bind(BlockGuard.java:275)
10-04 16:39:22.526: WARN/System.err(4974): at org.apache.harmony.luni.net.PlainSocketImpl.bind(PlainSocketImpl.java:165)
10-04 16:39:22.526: WARN/System.err(4974): at java.net.ServerSocket.<init>(ServerSocket.java:123)
10-04 16:39:22.526: WARN/System.err(4974): at java.net.ServerSocket.<init>(ServerSocket.java:74)
10-04 16:39:22.526: WARN/System.err(4974): at com.*******.remote.RemoteHandlerListener$1.doInBackground(RemoteHandlerListener.java:114)
代码:
ServerSocket server;
try {
server = new ServerSocket();
server.setReuseAddress(true);
server.bind(new InetSocketAddress(serverport));
} catch (IOException e) {
e.printStackTrace();
return null;
}
while (true) {
BufferedReader inStream = null;
Socket client = null;
try {
client = server.accept();
inStream = new BufferedReader(new InputStreamReader( client.getInputStream()));
// read from stream
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inStream != null) {
try {
inStream.close();
} catch (IOException e) { }
}
if (client != null) {
try {
client.close();
} catch (IOException e) { }
}
}
}
try {
server.close();
} catch (IOException e) { }
在server.bind-statement上抛出异常。
编辑: 问题原因:由于accept-call阻塞,线程不会自行终止。该程序没有完全终止,套接字没有解除绑定。
解决方案:将SO_TIMEOUT设置为套接字并在while()循环中检查isCancelled。这样,如果你对它调用cancel(),线程就会完成。
答案 0 :(得分:0)
尝试打印所有捕获的异常的堆栈跟踪。这可能会有很大帮助。也许你发布的代码有问题。您正在创建try-catch块而无需处理异常。你甚至不知道是否有。
更新:下一步是确保您的应用程序真正停止。乍一看您的代码从不退出接受客户的无限循环。尝试修复它并在关闭serversocket后添加print语句:
try {
server.close();
System.out.println("Server successfully stopped.");
} catch (IOException e) { }
确保在应用程序的输出中找到它。
如果你想要马虎,你可以使用以下方法强制执行应用程序(以及serversocket):
System.exit(0);
答案 1 :(得分:0)
我同意 - 通常这表示重新启动无法正常终止服务器进程。不知怎的,它仍然在运行,因此端口仍然被阻止。
等待10分钟有点长。只需检查(如果可能)先前运行的java进程是否已终止。
答案 2 :(得分:0)
如果你还没有,你应该在Activity Lifecycles上学习Android开发者的东西。该文章的tl;博士是Android操作系统绝对不能保证应用程序什么时候会被杀死,除非它可以随时发生,这就是为什么它们提供onPause,onResume,onRestart等等。你不能永远保证你的应用程序将永远完全死亡,但你可以执行自己的清理工作,我建议在onPause内部杀死你的线程并关闭你的套接字(或其他一些管理)。
此外,当使用Java套接字(无论是否为Android)时,让程序终止成为关闭套接字的操作绝不是一个好习惯。你应该几乎总是在某种清理区域自己关闭它们。特别是在处理线程时。
更新:你说你正在回击然后重新启动。这不会调用onDestroy。 onDestroy仅在操作系统需要内存并完全杀死您的应用程序时调用(相当于在任务管理器中将其杀死)