java关闭serversocket并打开端口

java关闭serversocket并打开端口,java,timeout,serversocket,Java,Timeout,Serversocket,我正在创建一个基于Java的服务器 我正在使用服务器套接字接受传入消息 然而,在我的程序中的某个时刻,我希望服务器套接字侦听另一个端口 我关闭服务器套接字。用我的新端口启动一个新端口。一切都很好 但是,当我再次将服务器套接字更改为上一个端口时,它会给我一个错误 我读到一些信息,服务器套接字在我关闭后处于超时状态 所以我的问题是: 我是否可以绕过服务器套接字的此超时状态,并在关闭端口并希望再次侦听同一端口后使其再次可用 编辑:创建和侦听服务器套接字的my函数&使服务器套接字无效并立即创建新套接字

我正在创建一个基于Java的服务器

我正在使用服务器套接字接受传入消息

然而,在我的程序中的某个时刻,我希望服务器套接字侦听另一个端口

我关闭服务器套接字。用我的新端口启动一个新端口。一切都很好

但是,当我再次将服务器套接字更改为上一个端口时,它会给我一个错误

我读到一些信息,服务器套接字在我关闭后处于超时状态

所以我的问题是: 我是否可以绕过服务器套接字的此超时状态,并在关闭端口并希望再次侦听同一端口后使其再次可用


编辑:创建和侦听服务器套接字的my函数&使服务器套接字无效并立即创建新套接字的my函数

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

堆栈跟踪错误:

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)

编辑: 第二次尝试修复无效:

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);
    }
}
同样,这正常工作。我可以浏览我的html页面。当我通过其中一个网页更改端口号时,它会正确存储并在我的存储xml文件中更改。 但是,当我更改套接字并立即通过该套接字导航到某个页面时,它表示该套接字已关闭,并且在我重新启动应用程序之前无法工作

我仍在寻找一种方法来避免重启


我解开了谜团。 问题是我只需要重新构建我的类,以便更好地支持线程。我没有关闭套接字然后创建一个新线程,而是启动了一个新线程,然后关闭了套接字。经过一点摆弄,它似乎工作得很好


感谢您的回复和支持。

这是操作系统正常的服务器套接字行为。操作系统在等待超时状态下保持端口打开。若要解决此问题,请尝试使用
ServerSocket.setReuseAddress(布尔启用)
。这将启用/禁用
SO\u REUSEADDR
socket选项。有关文件

引用方法的javadoc
setReuseAddress

TCP连接关闭时,连接可能会保持超时状态 连接关闭后一段时间内的状态(通常为 称为时间等待状态或2MSL等待状态)。申请 使用已知的套接字地址或端口可能无法 如果存在连接,则将套接字绑定到所需的SocketAddress 处于涉及套接字地址或端口的超时状态

在绑定套接字之前使用 绑定(SocketAddress)允许绑定套接字,即使 以前的连接处于超时状态


用于查看系统中所有打开的端口。您可以关闭正在使用的端口

发布您的代码,否则没有人可以帮助您。您会遇到什么错误?这是ServerSocket ss=new ServerSocket(1000);ss.close();ss=新服务器插座(1000);你是什么意思>?我正在寻找一个一般性的答案,但是是的,编辑生成了我的自定义case@EvgeniyDorofeev这就是我目前正在做的。但它不起作用。我试图做到的是,我的服务器会对端口号的更改做出反应。@Totumus Maximus在您进行编辑后,您似乎正在使用这种方式。仍然面临同样的问题吗?javadoc声明在绑定套接字之前需要
setReuseAddress
newserversocket(端口)
已将套接字绑定到该端口。您应该使用创建未绑定套接字的
newserversocket()
,然后
setReuseAddress
并将其绑定到首选套接字port@JonasAdler:让我试试看,看看server=newserversocket();server.setReuseAddress(true);bind(新的InetSocketAddress(portnr));似乎不起作用either@TotumusMaximus你能把stacktrace添加到你的问题中吗?有mac的替代方案吗?打开一个终端,写下netstat-a@claj是的,你可以使用netstat。但这可以用来关闭和停止进程。