【发布时间】:2018-07-01 03:04:20
【问题描述】:
我正在开发 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 状态。我可以连续更改几次,每次都能正常工作,但端口没有被释放。我花了相当长的时间研究这个,从我读到的内容看来我做的一切都是正确的(显然不是!)。
你们的任何意见都会有所帮助。
干杯!
【问题讨论】:
-
我再次仔细阅读了我的代码,我认为中断线程可能会导致它实际上没有运行 socket.close() 方法。我删除了该行,通过将运行变量设置为 false 来让线程自然终止,但即使这样也不会释放端口。
标签: java sockets server port release