I have a java.nio.channels.ServerSocketChannel which I initialised as follows:

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

When I send the first message from client it is successfully delivered to server and the client program exits. Then trouble begins. When I initialise the client again and try to establish at the same port and address of the server as I did the first time, I get a

java.net.BindException: Address already in use: connect

exception even though I closed the associated channel/socket. I have been renewing the ServerSocketChannel and InetSocketAddressobjects because as my client instance has to shut down after a write, I have to disengage that channel and since I cannot reuse a channel after it has been closed, I have to make a new object everytime. My theory is since the channel reference is reassigned each time, the orphaned object becomes GC meat, but since the close() method apparently is not working properly, the channel is still alive and until GC collects it my port will be hogged. Nevertheless I tried keeping the initialisation of ServerSocketChannel and InetSocketAddress objects before the while loop, but this did not help, and the same exception occurred after the first write, as before.

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

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

For clarity , here is how I connect from the 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();
有帮助吗?

解决方案

It looks like you're confusing client and server. Normally, server starts only once and binds to s port. Usually, there's no need to close there anything as the port gets freed when the program exits. Obviously, you must close the Sockets obtained by ServerSocket.accept(), but that's another story.

I guess you've got confused by your variable names (just like it happened to me as I started with this). Try to call all things according to their type, here was Hungarian really helpful for me.


The code I wrote for testing this is long, stupid, and boring. But it seems to work.

其他提示

It may also be helpful to do:

channel.setOption(StandardSocketOptions.SO_REUSEADDR, true);

Search for information about this option to learn more.

do ch.close() as well to GC the client socket.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top