首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DatagramChannel.close()在Windows上保持端口开放

DatagramChannel.close()在Windows上保持端口开放
EN

Stack Overflow用户
提问于 2012-10-19 15:08:53
回答 2查看 1.8K关注 0票数 2

我正在实施一个发现过程:

  • 打开UDP套接字以侦听给定端口上的广播响应。
  • 发送一些请求(并期待稍后的响应)
  • 在给定时间后关闭UDP套接字。

第一个电话有效。但其他调用会出现绑定错误。已在使用的地址:绑定

我正在运行Windows 7。我做了一些测试,发现在channel.close()之后,Netstat仍然提供:

netstat -a -b -sp udp \ grep 55224

UDP 0.0.0.0:55224

因此,udp端口仍然在OS级别打开。

我搜索了网络,这可能是os级的漏洞:Some java Datagram Socket questions

我运行了两个测试,一个使用NIO通道,另一个不使用(来自web上的测试)。我在NIO版本中重复我的错误,但是如果我不使用NIO,它就会工作。

任何人都可以告诉我如何使它与NIO一起工作。目标平台是Android,我不想总是听广播,但只听一段重复的时间。

测试插座

代码语言:javascript
复制
    public void testConnectCloseWithSocket() {
    long tCumulative = 0;
    int errAt = -1;
    System.out.println("start...");
    for (int i = 0; i < 4000; i++) {
        try {
            errAt = i;
            DatagramSocket result = new DatagramSocket(null);
            result.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
            result.close();

            //success at last
            tCumulative = 0;

        } catch (Exception e) {
            System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());

            tCumulative+=50;
            try {
                Thread.sleep(50);
            } catch (InterruptedException e1) {


            }
            i--;
        }
    }
    System.out.println("end...");

}

结果SOCKET<

开始..。错误(at=1319) (waited=0ms):已在使用的地址:无法绑定

错误(at=1438) (waited=0ms):已在使用的地址:无法绑定

错误(at=1587) (waited=0ms):已在使用的地址:无法绑定

错误(at=1740) (waited=0ms):已在使用的地址:无法绑定

结束..。

我确实犯了一些错误,但是插座被正确关闭了.可以满足我的需要

用通道测试

代码语言:javascript
复制
    public void testConnectCloseWithChannel() {
    long tCumulative = 0;
    int errAt = -1;
    System.out.println("start...");
    for (int i = 0; i < 4000; i++) {
        try {
            errAt = i;
            Selector selector = Selector.open();
            DatagramChannel channel = DatagramChannel.open();
            channel.configureBlocking(true);
            channel.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
            SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
            clientKey.cancel();
            channel.close();

            //success at last
            tCumulative = 0;

        } catch (Exception e) {
            System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());

            tCumulative+=50;
            try {
                Thread.sleep(tCumulative);
            } catch (InterruptedException e1) {


            }
            i--;
        }
    }
    System.out.println("end...");

}

注意:对channel.register进行了注释,测试工作。

结果与渠道

开始..。错误(at=0) (waited=0ms):空错误(at=0) (waited=50ms):已经使用的地址:绑定

错误(at=0) (waited=100ms):已在使用的地址:绑定

错误(at=0) (waited=150ms):地址已在使用:绑定.

谢谢你的帮助

EN

回答 2

Stack Overflow用户

发布于 2012-10-19 15:14:16

我确实犯了一些错误,但是插座被正确关闭了.可以满足我的需要

不,如果您有错误,您的通道没有正确关闭。

您必须在close块的finally子句中执行try

代码语言:javascript
复制
Selector selector = Selector.open();
try
{
  DatagramChannel channel = DatagramChannel.open();

  try
  {
    channel.configureBlocking(true);
    channel.socket().bind(
      new InetSocketAddress(InetAddress.getLocalHost(), 9005)
    );
    SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
    clientKey.cancel();
  }
  finally
  {
    channel.close();
  }
}
finally
{
  selector.close( )
}
票数 3
EN

Stack Overflow用户

发布于 2012-10-19 21:17:21

如果通道已在Selector中注册,则通道关闭的某些部分将推迟到下一个select()。它被记录在Selector,AbstractSelector,SelectorSpi,SelectableChannel,AbstractSelectableChannel森林的某个地方,在那里,当我需要它时,我永远找不到它。如果关闭通道时处于select循环和线程中,则可以通过调用selectNow()使其立即生效。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12977164

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档