gpt4 book ai didi

java - ServerSocket close 方法不释放端口

转载 作者:太空宇宙 更新时间:2023-11-04 10:46:18 35 4
gpt4 key购买 nike

我正在开发 2 个应用程序(网络应用程序和独立应用程序)。我已在 Web 应用程序中内置了功能,以便用户能够从网页重新启动独立应用程序的某些模块。我实现此目的的方法是使用 ServerSocket 对象,该对象监听在数据库中配置为参数的端口。这是监听传入请求的服务器端的简化版本:

try
{
int port = Integer.parseInt(globalParamService.findByName("serviceInterconnectPort").getValue());
ServerSocket serverSocket = new ServerSocket(port);
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully started web client connector on port " + port);
while(running)
{
socket = serverSocket.accept();
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Incoming request from web client");
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
if (message.contains("Restart Web Client Connector"))
{
if (!main.isWebClientConnectorRestarting())
{
main.restartWebClientConnector();
String returnMessage = "Done\n";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
bw.flush();

os.close();
osw.close();
bw.close();
}
else
{
String returnMessage = "Request cancelled\n";
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write(returnMessage);
bw.flush();

os.close();
osw.close();
bw.close();
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}
}

is.close();
isr.close();
br.close();
socket.close();
}
}
catch (Exception ex)
{
logEntryService.logError(LogEntry.CONNECTIVITY, "Error processing restart request from web client : " + ex.getMessage());
}

部署我的 2 个应用程序后,用户可能需要更改此监听器运行的端口。当他们从网络应用程序中更改它时,我会在数据库中更新它之前提取未更改的端口并将其发送到以下方法:

public void restartWebClientConnector(int oldPort)
{
Thread t = new Thread(() ->
{
try
{
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Connecting to port " + oldPort + " to restart web client connector");
InetAddress address = InetAddress.getByName("localhost");
socket = new Socket(address, oldPort);
logEntryService.logDebug(LogEntry.CONNECTIVITY, "Successfully connected to port " + oldPort);
OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw);
bw.write("Restart Web Client Connector\n");
bw.flush();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String message = br.readLine();
if (message.compareTo("Done") == 0)
{
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Web client connector restart request acknowledged");
}
else
{
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}

os.close();
osw.close();
bw.close();
is.close();
isr.close();
br.close();
socket.close();
}
catch (IOException | NumberFormatException ex)
{
logEntryService.logError(LogEntry.CONNECTIVITY, "Error sending web client connector restart command : " + ex.getMessage());
}
});
t.start();
}

然后,此方法调用以下代码,该代码终止我的监听器线程并在新更新的端口号上重新初始化它:

public void restartWebClientConnector()
{
if (!webClientConnectorRestarting)
{
webClientConnectorRestarting = true;
webClientConnector.setRunning(false);
webClientConnectorThread.interrupt();
initWebClientConnector();
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully restarted web client connector");
webClientConnectorRestarting = false;
}
}

private void initWebClientConnector()
{
logEntryService.logInfo(LogEntry.CORE, "Initializing web connector");

try
{
webClientConnector = new WebClientConnector(this, globalParamService, logEntryService);
webClientConnectorThread = new Thread(threads, webClientConnector);
webClientConnectorThread.setName("Web Client Connector Thread");
webClientConnectorThread.start();
}
catch (Exception ex)
{
logEntryService.logError(LogEntry.CORE, "Error initializing messaging process : " + ex.getMessage());
}
}

一切都很好,除了一件事:尽管明确关闭了我能想到的所有内容,但旧端口号并未释放。从 Web 客户端更改端口后执行 netstat -a 时,旧端口仍列在 LISTENING 状态中。我可以连续更改几次,每次都有效,但端口没有释放。我花了相当长的时间研究这个问题,从我读到的内容来看,我所做的一切都是正确的(显然不是!)。

无论你们提供什么意见都会有所帮助。

干杯!

最佳答案

我建议您使用资源 try block ,或者至少使用 try-finally block 来确保资源关闭:

    int port = Integer.parseInt(globalParamService.findByName("serviceInterconnectPort").getValue());
try (ServerSocket serverSocket = new ServerSocket(port)) {
logEntryService.logInfo(LogEntry.CONNECTIVITY, "Successfully started web client connector on port " + port);
while (running) {
try (Socket socket = serverSocket.accept();
InputStream is = socket.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr)) {
String message = br.readLine();
if (message.contains("Restart Web Client Connector")) {
if (!main.isWebClientConnectorRestarting()) {
main.restartWebClientConnector();
String returnMessage = "Done\n";
try (OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw)) {
bw.write(returnMessage);
bw.flush();
}
} else {
String returnMessage = "Request cancelled\n";
try (OutputStream os = socket.getOutputStream();
OutputStreamWriter osw = new OutputStreamWriter(os);
BufferedWriter bw = new BufferedWriter(osw)) {
bw.write(returnMessage);
bw.flush();
}
logEntryService.logWarning(LogEntry.CONNECTIVITY, "Web client connector restart request cancelled, restart already in progress");
}
}
}
}
} catch (IOException ex) {
logEntryService.logError(LogEntry.CONNECTIVITY, "Error processing restart request from web client : " + ex.getMessage());
}

关于java - ServerSocket close 方法不释放端口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48382324/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com