简体   繁体   English

java关闭一个serversocket并打开端口

[英]java closing a serversocket and opening up the port

I'm creating a Java based server. 我正在创建一个基于Java的服务器。

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: 错误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. 我可以浏览我的html页面。 When I change my port number via one of the webpages it is properly stored and changed in my storage xml files. 当我通过其中一个网页更改端口号时,它会在我的存储xml文件中正确存储和更改。 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. 这是OS的正常服务器套接字行为。 The OS keeps the port open in WAIT_TIMEOUT state. 操作系统在WAIT_TIMEOUT状态下保持端口打开。 To get around this, try using ServerSocket.setReuseAddress(boolean on) . 要解决此问题,请尝试使用ServerSocket.setReuseAddress(boolean on) This will enable/disable the SO_REUSEADDR socket option. 这将启用/禁用SO_REUSEADDR套接字选项。 Check here for Documentation. 点击此处查看文档。

Quoting the javadoc of method setReuseAddress 引用方法setReuseAddress的javadoc

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). 当TCP连接关闭时,连接可能在连接关闭后的一段时间内保持超时状态(通常称为TIME_WAIT状态或2MSL等待状态)。 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. 对于使用众所周知的套接字地址或端口的应用程序,如果在涉及套接字地址或端口的超时状态中存在连接,则可能无法将套接字绑定到所需的SocketAddress。

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. 在使用bind(SocketAddress)绑定套接字之前启用SO_REUSEADDR允许套接字绑定,即使先前的连接处于超时状态。

Use TCPview to see all the opened ports in your system. 使用TCPview查看系统中所有已打开的端口。 You can close those ports which are in use. 您可以关闭正在使用的端口。

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

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