Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DatagramChannel.close()在Windows上保持端口打开_Java_Udp_Nio - Fatal编程技术网

Java DatagramChannel.close()在Windows上保持端口打开

Java DatagramChannel.close()在Windows上保持端口打开,java,udp,nio,Java,Udp,Nio,我正在实施一个发现过程,该过程: 打开UDP套接字以侦听给定端口上的广播响应 发送一些请求(并期待稍后的响应) 在给定的时间段后关闭UDP套接字 第一个电话有效。但另一个调用得到绑定错误。已在使用的地址:bind 我正在运行Windows7。我做了一些测试,发现在一个通道之后;Netstat仍然提供: netstat-a-b-sp udp | grep 55224 UDP 0.0.0.0:55224: 因此,udp端口仍然在操作系统级别打开 我搜索了web,可能是操作系统级别的漏洞: 我运行

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

  • 打开UDP套接字以侦听给定端口上的广播响应
  • 发送一些请求(并期待稍后的响应)
  • 在给定的时间段后关闭UDP套接字
第一个电话有效。但另一个调用得到绑定错误。已在使用的地址:bind

我正在运行Windows7。我做了一些测试,发现在一个通道之后;Netstat仍然提供:

netstat-a-b-sp udp | grep 55224

UDP 0.0.0.0:55224:

因此,udp端口仍然在操作系统级别打开

我搜索了web,可能是操作系统级别的漏洞:

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

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

测试插座
public void testConnectCloseWithSocket(){
长t累积=0;
内部勘误表=-1;
System.out.println(“开始…”);
对于(int i=0;i<4000;i++){
试一试{
勘误表=i;
DatagramSocket结果=新DatagramSocket(空);
bind(新的InetSocketAddress(InetAddress.getLocalHost(),9005));
result.close();
//终于成功了
t累积=0;
}捕获(例外e){
System.out.println(“错误(at=“+errAt+”)(waited=“+tCumulative+”ms):“+e.getMessage());
t累计+=50;
试一试{
睡眠(50);
}捕捉(中断异常e1){
}
我--;
}
}
System.out.println(“结束…”);
}

结果套接字 我确实收到了一些错误,但套接字已正确关闭。。。那是 oki满足我的需要

不,如果您有错误,您的频道未正确关闭

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

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

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

感谢您的提示,在处理代码时,我注意到我没有关闭选择器。通过关闭它,一切正常:-)谢谢@这是因为我在回答中提出的问题。
    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...");

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