java关闭服务器套接字并打开端口



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

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

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

我关闭了服务器插座。用我的新港口开始一个新的。一切都很好。

但是,当我再次将服务器套接字更改为以前的端口时,会出现错误。

我读到过一些东西,在我关闭服务器套接字后,它会在超时状态下停留一段时间

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


EDIT:我的函数来制作和监听服务器套接字&我的功能是使服务器套接字无效,并在之后立即创建一个新套接字

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文件中。但是,当我更改套接字并通过该套接字立即导航到一个页面时,它会说它已关闭,在我重新启动应用程序之前无法工作。

我仍在寻找一种方法来规避这次重启。


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

这是操作系统的正常服务器套接字行为。操作系统在WAIT_TIMEOUT状态下保持端口打开。要解决此问题,请尝试使用ServerSocket.setReuseAddress(boolean on)。这将启用/禁用SO_REUSEADDR套接字选项。请在此处查看文档。

引用方法setReuseAddress的javadoc

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

在使用绑定套接字之前启用SO_REUSEADDRbind(SocketAddress)允许绑定套接字,即使上一个连接处于超时状态。

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

相关内容

  • 没有找到相关文章

最新更新