繁体   English   中英

java.nio.channels.ServerSocketChannel无法正确关闭

[英]java.nio.channels.ServerSocketChannel not closing properly

我有一个java.nio.channels.ServerSocketChannel ,其初始化如下:

while(true)
{
    ServerSocketChannel channel = ServerSocketChannel.open();
    InetSocketAddress serverSocket = new InetSocketAddress(host,port);
    channel.bind(serverSocket);
    SocketChannel ch = channel.accept();

    // Later on when I have read off data from a client, I want to shut this 
    // connection down and restart listening.
    channel.socket().close(); //Just trying to close the associated socket 
    // too because earlier approaches failed
    channel.close();
}               

当我从客户端发送第一条消息时,它已成功传递到服务器,并且客户端程序退出 然后麻烦开始了。 当我再次初始化客户端并尝试建立与第一次相同的服务器端口和地址时,

java.net.BindException:地址已在使用中:connect

即使我关闭了关联的通道/套接字也是如此。 我一直在更新ServerSocketChannelInetSocketAddress对象,因为在写入之后我的客户端实例必须关闭,因此我必须脱离该通道,并且由于关闭该通道后无法重用该通道,因此每次都必须创建一个新对象。 我的理论是,由于每次都重新分配channel引用,孤立的对象变成GC的主角,但是由于close()方法显然无法正常工作,通道仍然有效,直到GC收集到我的端口为止。 尽管如此,我还是尝试在while循环之前保留ServerSocketChannelInetSocketAddress对象的初始化,但这并没有帮助,并且第一次写入后发生了与以前相同的异常。

 ServerSocketChannel channel = ServerSocketChannel.open();
 InetSocketAddress serverSocket = new InetSocketAddress(host,port);
 channel.bind(serverSocket);

 while (true)
 {
    SocketChannel ch = channel.accept();
    //read from a client
 }              

为了清楚起见,这是我如何从客户端进行连接:

        SocketChannel ch=SocketChannel.open();
        ch.bind(new InetSocketAddress("localhost", 8077));
        InetSocketAddress address=new InetSocketAddress("localhost",8079);
                    //the address and port of the server
        System.out.print(ch.connect(address));
        ByteBuffer buf=ByteBuffer.allocate(48);
        buf.clear();
        buf.put("Hellooooooooooooooooooooooooo".getBytes());
        buf.flip();
        while(buf.hasRemaining()) {
            ch.write(buf);
        }
        ch.close();

看来您在混淆客户端和服务器。 通常,服务器仅启动一次并将s bind到s端口。 通常,由于程序退出时端口被释放,因此无需close任何内容。 显然,您必须关闭由ServerSocket.accept()获得的Socket ,但这是另一回事了。

我想您对变量名感到困惑(就像我刚开始时遇到的那样)。 尝试根据事物的类型来调用所有事物,这对匈牙利人真的很有帮助。


我为测试此代码而编写的代码又长又笨又无聊。 但这似乎有效。

这样做可能也会有所帮助:

channel.setOption(StandardSocketOptions.SO_REUSEADDR,true);

搜索有关此选项的信息以了解更多信息。

还要执行ch.close()来GC客户端套接字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM