| 
					
				 | 
			
			
				@@ -0,0 +1,120 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+package com.evps.comm.local.xnet.client; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.evps.comm.local.config.ApplicationConfig; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.evps.comm.local.dto.CenterDto; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.evps.comm.local.repository.ApplicationRepository; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.evps.comm.local.xnet.client.codec.EvpsLocalClientDecoder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.evps.comm.local.xnet.client.codec.EvpsLocalClientEncoder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import com.evps.comm.local.xnet.client.handler.EvpsLocalClientPacketInboundHandler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import io.netty.bootstrap.Bootstrap; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import io.netty.channel.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import io.netty.channel.socket.SocketChannel; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import io.netty.handler.logging.LogLevel; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import io.netty.handler.logging.LoggingHandler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import io.netty.handler.timeout.IdleStateHandler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.Getter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.RequiredArgsConstructor; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.Setter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import lombok.extern.slf4j.Slf4j; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.net.InetSocketAddress; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.concurrent.Callable; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import java.util.concurrent.TimeUnit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Slf4j 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Getter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@Setter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+@RequiredArgsConstructor 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+public class EvpsLocalClient implements Callable<Object> { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final CenterDto center; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final ApplicationConfig config; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final EvpsLocalClientBootstrapFactory bootstrapFactory; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final EvpsLocalClientPacketInboundHandler evpsLocalClientPacketInboundHandler; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private final EvpsLocalClientEncoder evpsLocalClientEncoder; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private Bootstrap bootstrap = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private ChannelFuture channelFuture = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private String ipAddress; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private int port; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public Object call() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.ipAddress = this.center.getIpAddress(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.port = this.center.getCommPort(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("EvpsLocalClient Start: [{}, {}], {}", this.center.getCenterId(), this.ipAddress, this.port); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (this.bootstrap == null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.bootstrap = this.bootstrapFactory.createBootstrap(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, this.config.getConnectionTimeout() * 1000); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.bootstrap.handler(new ChannelInitializer<SocketChannel>() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // 핸들러가 실행되는 순서는 추가된 순서에 의해 결정된다.(Inbound: head=>tail, Outbound: tail=>head, name2ctx) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                public void initChannel(SocketChannel ch) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (center.isCommLogging()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    IdleStateHandler idleStateHandler = new IdleStateHandler(center.getHeartBeat(), 0,0, TimeUnit.SECONDS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ch.pipeline().addLast("evpsLocalIdleStateHandler",           idleStateHandler); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ch.pipeline().addLast("evpsLocalClientDecoder",              new EvpsLocalClientDecoder());            // Decoding handler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ch.pipeline().addLast("evpsLocalClientPacketInboundHandler", evpsLocalClientPacketInboundHandler);     // Packet Inbound handler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ch.pipeline().addLast("evpsLocalClientEncoder",              evpsLocalClientEncoder);            // Encoding handler 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("EvpsLocalClient Connect Try: [{}, {}], {}", this.center.getCenterId(), this.ipAddress, this.port); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (this.channelFuture != null && this.channelFuture.channel() != null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.channelFuture.channel().close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            this.channelFuture = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.channelFuture = this.bootstrap.connect(new InetSocketAddress(this.ipAddress, this.port)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 연결 리스너 추가 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.channelFuture.addListener(new ChannelFutureListener() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            public void operationComplete(ChannelFuture future) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (future.isSuccess()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    channelOpen(future.channel()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    log.error("EvpsLocalClient Connect Failed: [{}, {}], {}, Exception {}", center.getCenterId(), center.getIpAddress(), center.getCommPort(), future.cause().getMessage()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 연결 종료 리스너 추가 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.channelFuture.channel().closeFuture().addListener(new ChannelFutureListener() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            @Override public void operationComplete(ChannelFuture future) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                channelClosed(future.channel()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 연결 성공시 처리 이벤트 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected void channelOpen(Channel channel) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.info("EvpsLocalClient Connect Success. [{}, {}], {}, Channel: {}", this.center.getCenterId(), this.center.getIpAddress(), this.center.getCommPort(), channel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ApplicationRepository.setCenterObject(channel, this.center); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.center.getNetState().connect(channel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 연결 종료시 처리 이벤트 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param channel 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected synchronized void channelClosed(Channel channel) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        log.warn("EvpsLocalClient Connect Closed. [{}, {}], {}, Channel: {}", this.center.getCenterId(), this.center.getIpAddress(), this.center.getCommPort(), channel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ApplicationRepository.setCenterObject(channel, null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        this.center.getNetState().disConnect(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        channel.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        channel.eventLoop().schedule(this, this.config.getRetryConnectSeconds(), TimeUnit.SECONDS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |