【问题标题】:At what point does Android free ports?Android 在什么时候释放端口?
【发布时间】:2015-06-25 15:02:02
【问题描述】:

我有一个子活动,它创建一个异步任务,该任务打开一个 Java ServerSocket 并在该 serverPort 上调用 accept()。

现在,在这个 Activity 的 onStop() 方法中,我调用了我的异步任务的 cancel()。在我的异步类中,在 onPostExecute() 和 onCancelled() 方法中,我关闭了 serverSocket(以及可能已打开的任何其他 dataStreams 或 Sockets)。

我所有的代码都能正常运行。通过调试,我知道如果我:

  1. 线性运行应用程序,直到 serverSocket 开始接受()连接。
  2. 点击后退按钮,关闭子活动并调用其 onStop() 方法,然后取消相关异步任务并调用 serverSocket 上的 close()。
  3. 再次运行子活动,创建新的异步线程,代码运行到我在与第一个相同的端口上创建 serverSocket 的位置。但是,它会引发 IO 异常,并表示该端口已在使用中。
  4. 无论我等待多长时间重新启动此子 Activity,都只会发出声称端口已被占用的 IO 异常。但是,执行以下操作:

    重启设备

    重新安装应用程序

    完全关闭应用程序(而不是仅仅从其父活动重新启动子活动)

似乎释放了端口。

Android 究竟如何刷新/释放您使用过的端口? 有什么方法可以以编程方式调用这些端口的刷新?

在出现明显问题之前,我使用的是 P2P 和 java 套接字,所以是的,我确实想使用直接连接到套接字并直接接受静态本地端口等。

编辑:格式化

EDIT2:更改后

serverSocket = new ServerSocket(portNumber);
socket = serverSocket.accept();

收件人:

serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress("192.168.49.1", 8000));
socket = serverSocket.accept();

我现在得到一个 java.net.BindException: bind failed: EADDNOTAVAIL (Cannot assign requested address) 异常。 (这只发生在第一组条件之后。应用程序的第一次运行仍然像以前一样正常运行)。

编辑 3:如果我找到正确执行此操作的方法,我会在编辑中发布它,但现在(调试)我只是走快速而肮脏的路线,并在任何时候完全杀死应用程序用户按下后退按钮并将应用程序重新启动到主要活动。这似乎清除了端口绑定。

【问题讨论】:

  • 代码片段会很有帮助。你的“异步任务”是什么——AsyncTask?你确定你要关闭套接字,那之后 accept() 会发生什么?

标签: java android sockets asynchronous ports


【解决方案1】:

几分钟后,仍然在网络中的请求不会在同一个四边形(源 ip、源端口、目标 ip、目标端口)上发送信息。这是跨所有操作系统(在 Windows、Linux、*BSD 等中)的 TCP 套接字的共同特征。您可以通过在套接字上指定 SO_REUSEADDR 选项来关闭它,这将告诉操作系统在关闭它后不要保留端口。

这里很好地解释了 SO_REUSEADDR 的用途:What is the meaning of SO_REUSEADDR (setsockopt option) - Linux?

【讨论】:

  • 我在 serverSocket 上调用了 serverSocket.setReuseAddress(false)。但是,该端口仍在使用中,我仍然从已使用的端口中获得 IOException。
  • 你想用 true 来调用它。显然,您必须在套接字的第一个和第二个版本上都这样做。不重复使用是默认设置。
  • 到目前为止,我还没有让它与 serverSocket.setReuseAddress(true) 或 serverSocket.setReuseAddress(false) 一起工作。是否需要在serverSocket = new ServerSocket(portNumber)之前调用它,或者我可以在之后调用它吗?
  • 需要在绑定socket之前调用。所以不要使用带有端口号的构造函数。使用无参数构造函数,调用它,然后调用 socket.bind(address, port)。
  • 应该注意的是,“几分钟后”苹果会连接到通过接受套接字连接的任何端口。 LISTENING 端口本身立即被释放。如果没有连接,也没有“几分钟后”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多