简体   繁体   中英

java closing a serversocket and opening up the port

I'm creating a Java based server.

I'm using a server socket to accept incoming messages.

However at some point within my program I want the server socket to listen to another port.

I close the server socket. And start a new one with my new port. Everything is fine.

However when I change the server socket to the previous port again, it gives me an error.

I've read things that the server socket stays a while in a timed-out state after I closed it.

So here is my question: Can I circumvent this timed-out state of the server socket and make my port available again after I closed it and want to listen to the same port again?


EDIT: my function to make and listen to a server socket & my function to invalidate a server socket and create a new one right after

public void makeServerSocketWithPort(int portnr) throws IOException, Exception
{
    server = new ServerSocket(portnr);
    server.setReuseAddress(true);
    while(!portchanged)
    {
        Socket sock = server.accept();
        System.out.println(server.getLocalPort());
        System.out.println(sock.getLocalPort());
        handler = new Requesthandler(sock); //should be in a thread
        System.out.println(server.getLocalPort());
        System.out.println(sock.getLocalPort());
    }

}

public void invalidateRequestHandler(int newPort)
{   
    if(server != null)
    {
       portchanged = true; 
        try {
            server.close();
        } catch (IOException ex) {
            Logger.getLogger(Controlserver.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    portchanged = false;
    makeServerSocketWithPort(newPort);
}

Error StackTrace:

Exception in thread "main" java.net.SocketException: Socket closed
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at stuff.Controlserver.makeServerSocketWithPort(Controlserver.java:63)
at stuff.Main.main(Main.java:44)

EDIT: a second try to fix it to no avail:

public void makeServerSocketWithPort(int portnr, boolean invalidated) throws IOException, Exception
{
    if(!invalidated)
    {
        server = new ServerSocket();
        server.setReuseAddress(true);
        server.bind(new InetSocketAddress(portnr));

        portchanged = false;
    }
    else
    {
        //TODO: invalidate the old requestHandler
        if(server != null)
        { 
            try 
            {
                server.close();
                server = null;
            } 
            catch (IOException ex) 
            {
                Logger.getLogger(Controlserver.class.getName()).log(Level.SEVERE, null, ex);
            }
        }

        if(server.isClosed())
        {
            System.out.println("closed biatch!");
        }
        else
        {
            System.out.println("surprise moddafakkaaaaa!!!");
        }

        //---------------------------------------------
        //then make new requestHandler with new port
        portchanged = true;
    }

    while(!portchanged)
    {
        if(server != null && !server.isClosed() && !invalidated)
        {
            Socket sock = server.accept();
            System.out.println(server.getLocalPort());
            System.out.println(sock.getLocalPort());
            System.out.println("test");
            handler = new Requesthandler(sock); //should be in a thread
            handler.start();
            System.out.println("ja harm");
            System.out.println(server.getLocalPort());
            System.out.println(sock.getLocalPort());
        }
        else
        {
            portchanged = true;
        }
    }

    if(portchanged)
    {
        portchanged = false;
        makeServerSocketWithPort(portnr, false);
    }
}

Again this works fine normally. I can navigate through my html pages. When I change my port number via one of the webpages it is properly stored and changed in my storage xml files. But when I changed my socket and navigate immidiately to a page through that socket, it says it is closed and is not working until i restart my application.

I'm still looking for a way to circumvent this restart.


Well I solved the mystery. Thing was I just needed to reconstruct my classes a bit to support the threading a bit better. Instead of closing the socket and then making a new thread I started a new thread and then closed the socket. After a bit of fiddling it appeared to work just fine.

Thanks for the replies and stuff.

This is the normal Server socket behavior by OS. The OS keeps the port open in WAIT_TIMEOUT state. To get around this, try using ServerSocket.setReuseAddress(boolean on) . This will enable/disable the SO_REUSEADDR socket option. Check here for Documentation.

Quoting the javadoc of method setReuseAddress

When a TCP connection is closed the connection may remain in a timeout state for a period of time after the connection is closed (typically known as the TIME_WAIT state or 2MSL wait state). For applications using a well known socket address or port it may not be possible to bind a socket to the required SocketAddress if there is a connection in the timeout state involving the socket address or port.

Enabling SO_REUSEADDR prior to binding the socket using bind(SocketAddress) allows the socket to be bound even though a previous connection is in a timeout state.

Use TCPview to see all the opened ports in your system. You can close those ports which are in use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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