java.nio.channels.ServerSocketChannel未正确关闭

问题描述 投票:1回答:3

我有一个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

异常,即使我关闭了相关的通道/套接字。我一直在更新ServerSocketChannelInetSocketAddressobjects,因为我的客户端实例必须在写入后关闭,我必须脱离该通道,因为我不能在它关闭后重用一个通道,我必须每次都创建一个新对象。我的理论是因为每次重新分配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();
java sockets garbage-collection nio
3个回答
3
投票

看起来你会混淆客户端和服务器。通常,服务器只启动一次,binds启动到s端口。通常,没有必要close有任何东西,因为当程序退出时端口被释放。显然,你必须关闭Socket获得的ServerSocket.accept()s,但这是另一个故事。

我猜你已经被你的变量名混淆了(就像我刚开始的时候一样)。尝试根据他们的类型打电话给所有的东西,这里匈牙利人对我很有帮助。


我为测试而写的code是漫长的,愚蠢的,无聊的。但似乎有效。


0
投票

它可能也有帮助:

channel.setOption(StandardSocketOptions.SO_REUSEADDR,true);

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


-3
投票

对客户端套接字执行ch.close()。

© www.soinside.com 2019 - 2024. All rights reserved.