Files
bapweb/src/com/eactive/eai/adapter/socket/service/SocketServer.java
T
Rinjae d6bf8e1943 init
2025-10-23 13:21:43 +09:00

455 lines
19 KiB
Java

package com.eactive.eai.adapter.socket.service;
import com.eactive.eai.adapter.socket.common.CommonLib;
import com.eactive.eai.adapter.socket.common.DiagLogger;
import com.eactive.eai.adapter.socket.common.SocketAdapterException;
import com.eactive.eai.adapter.socket.config.ConfigurationContext;
import com.eactive.eai.adapter.socket.config.SocketAdapterManager;
import com.eactive.eai.common.property.PropManager;
import com.eactive.eai.common.util.Logger;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Vector;
import java.nio.channels.ClosedSelectorException;
import java.util.HashMap;
public class SocketServer extends Thread implements SocketService {
private ConfigurationContext context;
private Vector<SocketService> threadPool;
private boolean active;
private Selector selector;
private ServerSocketChannel serverSocketChannel;
private ServerSocket serverSocket;
private Logger logger;
private HashMap<String, Integer> ipTable; // IP별 Connection 수 제한이 있는 경우 , KEY-RemoteIP, VALUE-Integer
//소켓 관련 프라퍼티 정보
public static final String PROP_GROUP_SOCKET = "socket";
public static final String PROP_BLOCK_IP_LIST = "block.ip.list"; //연결 거부 IP 리스트
public static final String PROP_BLOCK_SLEEP = "sleep.time"; //close 하기 전에 대기 시간
public SocketServer(ConfigurationContext context) {
String name = this.getName();
this.setName( context.getAdapterName() + "-LISTENER" + name.substring( name.lastIndexOf("-")) );
this.context = context;
active = true;
threadPool = new Vector<SocketService>();
logger = (Logger) SocketLogManager.getInstance().getLogger( this.context.getAdapterGroupName() );
ipTable = new HashMap<String, Integer>();
}
private int getTraceLevel() {
return context.getTraceLevel();
}
public void run() {
// Server Socket을 기동하는 순간 Connection없음을 나타내도록 Adapter Status를 false로 변경한다.
SocketAdapterManager.getInstance().changeAdapterStatus( this, false);
try {
openSelector();
} catch(IOException e) {
logger.error(CommonLib.getMessage("BECEAIMSA029", new String[] { context.getAdapterName(), context.getHostName() + ":" + context.getPortNumber(), e.getMessage() } ), e);
active = false;
SocketAdapterManager.getInstance().stop( context.getAdapterGroupName(), context.getAdapterName() );
}
Iterator<SelectionKey> it;
SocketChannel channel;
SelectionKey key;
while ( active ) {
try {
// select(miliseconds) : 대기시간
int i = selector.select(2000L);
if(i == 0) {
if ( threadPool == null || threadPool.size() == 0 ) {
SocketAdapterManager.getInstance().changeAdapterStatus( this, false );
}
continue;
}
} catch(IOException e) {
active = false;
shutdown();
break;
} catch( ClosedSelectorException e ) {
} catch( Exception e ) {
continue;
}
if ( selector == null || !selector.isOpen() ) break;
it = selector.selectedKeys().iterator();
while( it.hasNext() ) {
// 소켓 서버로 연결 요청이 있는 경우.
try {
key = it.next();
it.remove();
if ( !key.isValid() ) continue;
ServerSocketChannel server = (ServerSocketChannel)key.channel();
if ( !server.isOpen() ){
continue;
}
channel = server.accept();
if(channel == null) continue;
// L4에서 보내온 세션인 경우
String remoteIp = channel.socket().getRemoteSocketAddress().toString().substring(1,channel.socket().getRemoteSocketAddress().toString().indexOf(":") );
String blockIpList = PropManager.getInstance().getProperty(PROP_GROUP_SOCKET, PROP_BLOCK_IP_LIST);
if (( blockIpList != null) && ( blockIpList.indexOf(remoteIp) > -1 ) ) {
try {
long delayTime = 1000;
try {
delayTime = Long.parseLong(PropManager.getInstance().getProperty(PROP_GROUP_SOCKET, PROP_BLOCK_SLEEP));
} catch (Exception e) {}
if ( delayTime > 0 )
Thread.sleep(delayTime);
channel.socket().close();
channel.close();
} catch(IOException ie) {}
continue;
}
if ( context.getMaxConnection() > 0 && context.getMaxConnection() <= threadPool.size() ) {
try {
for ( int inx = 0; inx < threadPool.size(); inx++){
SocketService oldService = threadPool.get(inx);
if ( oldService.isActive()){
logger.warn( CommonLib.getMessage("BECEAIMSA022", new String[]{ context.getAdapterName(), Integer.toString( context.getMaxConnection() ),this.getSocketInfo( oldService.getCurrentSocket() ) } ) );
oldService.shutdown();
}
}
} catch (Exception e) {
logger.error( e.getMessage(), e);
}
}
// Client Socket별 (REMOTE IP) Connection 수 제한 있는 경우
if ( context.getConnLimitPerIp() > 0 ) {
String ip = channel.socket().getInetAddress().getHostAddress();
Integer connCount = ipTable.get( ip );
if ( connCount == null ) {
ipTable.put( ip, new Integer( 1 ) );
} else if ( connCount.intValue() < context.getConnLimitPerIp() ) {
int newCount = connCount.intValue() + 1;
ipTable.put( ip, new Integer( newCount ));
} else {
logger.error( CommonLib.getMessage("BECEAIMSA023", new String[]{ context.getAdapterName(), Integer.toString( context.getConnLimitPerIp() ),this.getSocketInfo( channel ) } ) );
try {
channel.socket().close();
channel.close();
} catch(IOException ie) {}
continue;
}
}
if ( getTraceLevel() >= DiagLogger.INFO ) {
logger.info( CommonLib.getMessage("BICEAIMSA033", new String[]{ context.getAdapterName(), this.getSocketInfo( channel ) } ) );
}
if ( this.context.isSocketReuse() ) {
channel.socket().setSoLinger(true, 100);
}
// 신규 Connection Process 쓰레드를 생성 후 수행시킨다...
if ( isForInbound() && context.getSocketType().equals( ConfigurationContext.SERVER_SOCKET ) ) {
InboundServer aProcess = new InboundServer(context, channel, this);
logger.debug("# INBOUND SOCKETSERVER CREATED.[" + this.getName() + "]");
//
threadPool.addElement( aProcess );
aProcess.start();
logger.debug("# INBOUND SOCKETSERVER STARTED.[" + this.getName() + "]");
synchronized ( threadPool ) {
if ( threadPool.size() == 1 ) {
SocketAdapterManager.getInstance().changeAdapterStatus( this, true );
}
}
} else if ( isForOutbound() ) {
// OutboundServer aProcess = new OutboundServer(context, channel, this);
// logger.debug("# OUTBOUND SOCKETSERVER CREATED.[" + this.getName() + "]");
// if ( !OutboundChannelManager.getInstance().hasChannel( context.getAdapterGroupName() )) {
// OutboundChannel connection = new OutboundChannel(context.getSessionTimeout()*1000);
// OutboundChannelManager.getInstance().addConnectionGroup( context.getAdapterGroupName(), connection );
// }
// threadPool.addElement( aProcess );
// aProcess.start();
// logger.debug("# OUTBOUND SOCKETSERVER STARTED.[" + this.getName() + "]");
// synchronized ( threadPool ) {
// if ( threadPool.size() == 1 ) {
// SocketAdapterManager.getInstance().changeAdapterStatus( this, true );
// }
// }
} else if ( isForIobound() ) {
IOboundServer aProcess = new IOboundServer(context, channel, this);
logger.debug("# IOBOUND SOCKETSERVER CREATED.[" + this.getName() + "]");
if ( !OutboundChannelManager.getInstance().hasChannel( context.getAdapterGroupName() )) {
OutboundChannel connection = new OutboundChannel(context.getSessionTimeout()*1000);
OutboundChannelManager.getInstance().addConnectionGroup( context.getAdapterGroupName(), connection );
}
threadPool.addElement( aProcess );
aProcess.start();
logger.debug("# IOBOUND SOCKETSERVER STARTED.[" + this.getName() + "]");
synchronized ( threadPool ) {
if ( threadPool.size() == 1 ) {
SocketAdapterManager.getInstance().changeAdapterStatus( this, true );
}
}
// } else {
// AdminServer aProcess = new AdminServer(context, channel, this);
// logger.debug("# ADMIN SOCKETSERVER CREATED.[" + this.getName() + "]");
// threadPool.addElement( aProcess );
// aProcess.start();
// logger.debug("# ADMIN SOCKETSERVER STARTED.[" + this.getName() + "]");
// synchronized ( threadPool ) {
// if ( threadPool.size() == 1 ) {
// SocketAdapterManager.getInstance().changeAdapterStatus( this, true );
// }
// }
}
// Process 쓰레드 Started
} catch(Exception e) {
logger.error(CommonLib.getMessage("BECEAIMSA030", new String[] { context.getAdapterName(), e.getMessage() } ), e);
logger.error( e.getMessage(), e);
}
} // End of While - it.hasNext
} // End of While - active
try {
closeSelector();
} catch( Throwable e ) {}
interrupt();
} // end of startup ...
public String getRemoteIPAddress() {
return null;
}
public Socket getCurrentSocket() {
return null;
}
public boolean idle(long timeout) {
return false;
}
public boolean connect() {
return true;
}
public void disconnect() {
}
public int getCurrentState() {
return CommonLib.PROCESSING_PROTOCOL;
}
public boolean isConnected() {
return true;
}
public void checkActivity() {
}
public synchronized void shutdown() {
active = false;
if ( threadPool != null ) {
for ( int i=0; i < threadPool.size(); i++ ) {
try {
SocketService service = (SocketService)threadPool.get(i);
if ( getTraceLevel() >= DiagLogger.INFO ) {
try {
logger.info( CommonLib.getMessage("BICEAIMSA031", new String[]{ context.getAdapterName(), this.getSocketInfo( service.getCurrentSocket() )} ) );
} catch( Exception e ) {}
}
service.shutdown();
} catch( Throwable e ) {logger.error( e.getMessage(), e);}
}
}
threadPool = null;
try {
closeSelector();
} catch (Throwable t) {logger.error( t.getMessage(), t);}
try {
serverSocket.close();
} catch (Throwable t) {logger.error( t.getMessage(), t);}
SocketAdapterManager.getInstance().changeAdapterStatus( this, false );
//*interrupt();
}
/**
* @return Returns the context.
*/
public ConfigurationContext getContext() {
return context;
}
/**
* @return Returns the active.
*/
public boolean isActive() {
return active;
}
public void notifyMessage() {
}
public void setControl(Object control) {
}
public void setLastActivity() {
}
private String getSocketInfo(SocketChannel channel) {
StringBuffer connInfo = new StringBuffer();
connInfo.append("Local Address=");
connInfo.append( channel.socket().getLocalAddress().getHostAddress()).append(":").append(channel.socket().getLocalPort()).append(", ");
connInfo.append("Remote Address=");
connInfo.append( channel.socket().getInetAddress().getHostAddress()).append(":").append(channel.socket().getPort());
return connInfo.toString();
}
private String getSocketInfo(Socket socket) {
StringBuffer connInfo = new StringBuffer();
if ( socket != null ) {
connInfo.append("Local Address=");
connInfo.append( socket.getLocalAddress().getHostAddress()).append(":").append(socket.getLocalPort()).append(", ");
connInfo.append("Remote Address=");
connInfo.append( socket.getInetAddress().getHostAddress()).append(":").append(socket.getPort());
}else {
connInfo.append("SOCKET IS NULL");
}
return connInfo.toString();
}
private boolean isForInbound() {
return ( this.context.getBoundUsage().equals( ConfigurationContext.INBOUND_SOCKET ));
}
private boolean isForIobound() {
return ( this.context.getBoundUsage().equals( ConfigurationContext.IOBOUND_SOCKET ));
}
private boolean isForOutbound() {
return ( this.context.getBoundUsage().equals( ConfigurationContext.OUTBOUND_SOCKET ));
}
public synchronized void quiesceShutdown(SocketService service) {
if ( threadPool == null ) return;
for ( int i=0; i < threadPool.size(); i++) {
SocketService aService = (SocketService) threadPool.elementAt( i );
if ( service != aService ) continue;
//service.shutdown();
if ( context.getConnLimitPerIp() > 0 ) {
String ip = service.getRemoteIPAddress();
if ( ip != null ) {
Integer connCount = (Integer)ipTable.get( ip );
if ( connCount != null ) {
int newCount = connCount.intValue() - 1;
if ( newCount < 0 ) newCount = 0;
ipTable.put( ip, new Integer( newCount ) );
}
}
}
threadPool.remove(i);
break;
}
// Adapter status 변경
if ( threadPool == null || threadPool.size() == 0 ) {
SocketAdapterManager.getInstance().changeAdapterStatus( this, false );
}
}
private void openSelector() throws IOException {
serverSocketChannel = ServerSocketChannel.open();
serverSocket = serverSocketChannel.socket();
selector = Selector.open();
if( context.getHostName() == null || context.getHostName().equals("*") || context.getHostName().equals("") || context.getHostName().equals("localhost")
|| context.getHostName().equals("0.0.0.0") || context.getHostName().equals("127.0.0.1") ) {
serverSocket.bind(new InetSocketAddress(context.getPortNumber()), 1024);
if ( getTraceLevel() >= DiagLogger.INFO ) {
logger.info( CommonLib.getMessage("BICEAIMSA032", new String[]{ context.getAdapterName(), context.getHostName(), Integer.toString(context.getPortNumber()) }) );
}
} else {
serverSocket.bind(new InetSocketAddress(context.getHostName(), context.getPortNumber()), 1024);
if ( getTraceLevel() >= DiagLogger.INFO ) {
logger.info( CommonLib.getMessage("BICEAIMSA032", new String[]{ context.getAdapterName(), context.getHostName(), Integer.toString(context.getPortNumber()) }) );
}
}
serverSocketChannel.configureBlocking(false);
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
synchronized ( threadPool ) {
if ( threadPool.size() == 0 ) {
SocketAdapterManager.getInstance().changeAdapterStatus( this, false );
}
}
}
private void closeSelector() throws IOException {
if(selector != null) {
for(Iterator<SelectionKey> iterator = selector.keys().iterator(); iterator.hasNext();)
try {
SelectionKey selectionkey = iterator.next();
ServerSocketChannel serversocketchannel = (ServerSocketChannel)selectionkey.channel();
selectionkey.cancel();
serversocketchannel.socket().close();
serversocketchannel.close();
iterator.remove();
}catch(UnsupportedOperationException e) {
// Do nothing!!!
}catch(IOException e) {
logger.error( e.getMessage(), e);
}catch(Exception e) {
logger.error( e.getMessage(), e);
}
selector.close();
}
} // end of closeSelector...
public void disconnect(String localHostname, int localPortNumber)
throws SocketAdapterException {
}
public void setContext(ConfigurationContext context) {
this.context = context;
}
public long getFirstActivity() {
return 0;
}
public long getLastActivity() {
return 0;
}
}