Java HAPI-如何正确停止SimpleServer并防止进一步连接
我正在构建一个应用程序,其中包含几个由CommunicationProcess类管理的服务器和客户端HL7连接。应用程序的部分功能是在添加新连接时重新启动该进程。客户端连接不会造成问题,因为一旦客户端停止,服务器端就无法重新连接。然而,对于服务器连接,我似乎立即从(相当激烈的)客户端重新连接。这是我必须停止服务器连接的代码:Java HAPI-如何正确停止SimpleServer并防止进一步连接,java,server,connection,hapi,Java,Server,Connection,Hapi,我正在构建一个应用程序,其中包含几个由CommunicationProcess类管理的服务器和客户端HL7连接。应用程序的部分功能是在添加新连接时重新启动该进程。客户端连接不会造成问题,因为一旦客户端停止,服务器端就无法重新连接。然而,对于服务器连接,我似乎立即从(相当激烈的)客户端重新连接。这是我必须停止服务器连接的代码: public void disconnect() { usageServer.getRemoteConnections().forEach((connection
public void disconnect()
{
usageServer.getRemoteConnections().forEach((connection) -> connection.close());
usageServer.stopAndWait();
usageServer.getRemoteConnections().forEach((connection) -> connection.close());
}
public void stop()
{
running.set(false);
disconnect();
}
这是我对connectionReceived的实现:
@Override
public void connectionReceived(Connection theC)
{
if (running.get())
{
setStatus(ConnectionStatus.CONNECTED);
}
else
{
theC.close();
}
}
如您所见,我们的想法是在从CommunicationProcess类接收停止信号(拒绝任何新连接)时将全局AtomicBoolean设置为false,并停止服务器。无论如何,这仍然允许客户端在此过程中保持连接。客户端是一个我不允许命名的应用程序,但它已经存在了十多年,我知道事实上它不会成为问题,因为多年来我一直支持它作为我日常工作的一部分,它的行为根本不是这样的
你知道为什么我的代码没有真正终止连接吗?我觉得我已经研究了很多这个API,我没有找到一种方法来注销连接侦听器,这可能会解决这个问题。此外,我无法扩展这些服务器类,因为所有的东西都被极度地封装和私有化了
谢谢我正在查看HAPI库的代码 您所描述的行为原因可能如下 当服务器启动时,它们会创建一个名为
acceptorhread
的组件。顾名思义,该线程的职责是初始化将用于接收传入客户端连接的ServerSocket
,并接受它们
与API提出的每个服务
抽象一样,该线程在如下循环中运行:
/**
*运行线程。
*
*@see java.lang.Runnable#run()
*/
公开最终作废运行(){
试一试{
启动后();
debug(“线程{}进入主循环”,名称);
while(isRunning()){
句柄();
startupLatch.countDown();
}
调试(“线程{}离开主循环”,名称);
}捕获(运行时异常t){
如果(t.getCause()!=null){
serviceExitedWithException=t.getCause();
}否则{
serviceExitedWithException=t;
}
log.warn(“由于异常退出主循环的线程:,t”);
}捕获(可丢弃的t){
serviceExitedWithException=t;
log.warn(“由于异常退出主循环的线程:,t”);
}最后{
startupLatch.countDown();
后终止();
}
}
当您在服务器中调用方法stopAndWait
时,它也会尝试停止此线程
stop进程基本上更改了控制组件``ìsRunning()``是否运行的布尔
标志
如您所见,尽管它将标志设置为false
,但循环中方法句柄的调用仍然必须结束
这是acceptorhread
handle
方法的实现:
@覆盖
受保护的无效句柄(){
试一试{
套接字s=ss.accept();
socketFactory。配置新的AcceptedSocket;
如果(!queue.offer(新的AcceptedSocket))){
错误(“拒绝排队服务器端套接字{}”,s);
s、 close();
}否则
debug(“排队的服务器端套接字{}”,s);
}catch(SocketTimeoutException e){/*好-刚刚超时*/
log.trace(“等待时未建立连接”);
}捕获(IOE异常){
log.error(“接受连接时出错”,e);
}
}
如您所见,该方法调用ServerSocket.accept
,从而允许新的传入连接
为了断开此服务器端套接字的连接,我们可以从另一个线程调用close
事实上,此过程是通过acceptorread
后终止
方法实现的:
@覆盖
受保护的无效后终止(){
试一试{
如果(ss!=null&&!ss.isClosed())
ss.close();
}捕获(IOE异常){
log.warn(“停止线程时出错”,e);
}
}
不幸的是,你是对的,API非常接近没有明确的方法可以做到这一点
一种可能的解决方案是实现您自己的HL7Service
,命名为MySimpleServer
,使用SimpleServer
的代码作为基线,只需在终止后更改方法的实现即可:
/**
*封闭式插座
*/
@凌驾
受保护的无效后终止(){
超级后终止();
//终止服务器端套接字
接受者。后终止();
//终止接受线程本身
acceptor.close();
}
请注意:我们不调用acceptor.stop()
而是调用acceptor.aftermination()
直接关闭底层服务器端套接字
为了避免acceptorhread
中的handle
方法引发的错误,我们还可以从原始类中实现一个新类,或者仅尝试覆盖handle
方法,以便在服务器端套接字关闭时考虑:
@覆盖
受保护的无效句柄(){
试一试{
if(ss.isClosed()){
debug(“服务器端套接字已关闭。不允许新连接”);
返回;
}
套接字s=ss.accept();
socketFactory。配置新的AcceptedSocket;
如果(!queue.offer(新的AcceptedSocket))){
错误(“拒绝排队服务器端套接字{}”,s);
s、 close();
}否则
debug(“排队的服务器端套接字{}”,s);
}catch(SocketTimeoutException e){/*好-刚刚超时*/
log.trace(“无连接