Browse Source

ice104 module-增加
1:服务端未启动,保持一直重连
2:连接过冲中,中断,保持一直重连
3:优化单例工厂,确保每次线程启动的是同一个连接线路。否则多个线程开启的是多个连接线路,无法监控

hfxc226 2 years ago
parent
commit
6093b217dd

+ 3 - 1
platform-iec/src/main/java/com/platform/iec/IecApplication.java

@@ -3,6 +3,7 @@ package com.platform.iec;
 import com.platform.iec.master.MasterSysDataHandler;
 import com.ydl.iec.iec104.config.Iec104Config;
 import com.ydl.iec.iec104.server.Iec104MasterFactory;
+import com.ydl.iec.util.Iec104Util;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.SpringApplication;
@@ -21,6 +22,7 @@ import java.util.TimeZone;
 @Order(1)
 @Slf4j
 public class IecApplication implements CommandLineRunner {
+
     public static void main(String[] args) {
         TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
         SpringApplication.run(IecApplication.class, args);
@@ -32,7 +34,7 @@ public class IecApplication implements CommandLineRunner {
         Iec104Config iec104Config  = new Iec104Config();
         iec104Config.setFrameAmountMax((short) 1);
         iec104Config.setTerminnalAddress((short) 1);
-        Iec104MasterFactory.createTcpClientMaster("127.0.0.1", 2404).setDataHandler(new MasterSysDataHandler()).setConfig(iec104Config).run();
+        Iec104MasterFactory.createTcpClientMaster(Iec104Util.host, Iec104Util.port).setDataHandler(new MasterSysDataHandler()).setConfig(iec104Config).run();
         Thread.sleep(1000000);
     }
 }

+ 1 - 0
platform-iec/src/main/java/com/platform/iec/master/MasterSysDataHandler.java

@@ -76,4 +76,5 @@ public class MasterSysDataHandler implements DataHandler {
 		String strContent = ByteUtil.byteArrayToHexString(bytes);
 		System.out.println(strContent);
 	}
+
 }

+ 1 - 1
platform-iec/src/main/java/com/ydl/iec/iec104/server/Iec104Master.java

@@ -12,7 +12,7 @@ public interface Iec104Master {
 	 * 服务启动方法
 	 * @throws Exception
 	 */
-	void run() throws Exception;
+	void run();
 	
 	/**
 	 * 

+ 18 - 14
platform-iec/src/main/java/com/ydl/iec/iec104/server/Iec104MasterFactory.java

@@ -3,24 +3,28 @@ package com.ydl.iec.iec104.server;
 import com.ydl.iec.iec104.server.master.Iec104TcpClientMaster;
 
 /**
- * 主站 工厂类
- * @ClassName:  Iec104MasterFactory   
+ * 主站 工厂类:确保单例模式,否则新线程启动新的
+ *
+ * @ClassName: Iec104MasterFactory
  * @Description: IEC104规约主站
  * @author: YDL
- * @date:   2020年5月19日 上午10:22:59
+ * @date: 2020年5月19日 上午10:22:59
  */
 public class Iec104MasterFactory {
 
- 
+    private static Iec104Master iec104Master = null;
 
-	/**
-	* @Title: createTcpClientMaster
-	* @Description: 创建一个TCM客户端的104主站
-	* @param host 从机地址
-	* @param port 端口
-	* @return
-	 */
-	public static  Iec104Master createTcpClientMaster(String host, int port) {
-		return new Iec104TcpClientMaster(host, port);
-	}
+    /**
+     * @param host 从机地址
+     * @param port 端口
+     * @return
+     * @Title: createTcpClientMaster
+     * @Description: 创建一个TCM客户端的104主站
+     */
+    public static Iec104Master createTcpClientMaster(String host, int port) {
+        if(iec104Master == null){
+            iec104Master = new Iec104TcpClientMaster(host, port);
+        }
+        return iec104Master;
+    }
 }

+ 34 - 35
platform-iec/src/main/java/com/ydl/iec/iec104/server/master/Iec104ClientInitializer.java

@@ -14,47 +14,46 @@ import lombok.Setter;
 import lombok.experimental.Accessors;
 
 /**
- * 
-* @ClassName: Iec104ServerInitializer  
-* @Description: 104协议 处理链 
-* @author YDL 
-* @date 2020年5月13日
+ * @author YDL
+ * @ClassName: Iec104ServerInitializer
+ * @Description: 104协议 处理链
+ * @date 2020年5月13日
  */
 @Setter
 @Accessors(chain = true)
 public class Iec104ClientInitializer extends ChannelInitializer<SocketChannel> {
 
 
-	private DataHandler dataHandler;
+    private DataHandler dataHandler;
 
-	private Iec104Config iec104Config;
-	
-	/**
-	 * 初始化处理链
-	 */
-	@Override
-	public void initChannel(SocketChannel ch) throws Exception {
-		if (iec104Config == null) {
-			Iec104ThreadLocal.setIec104Config(iec104Config);
-		} else {
-			Iec104ThreadLocal.setIec104Config(new DefaultIec104Config());
-		}
-		ChannelPipeline pipeline = ch.pipeline();
-		// 沾包拆包工具
-		pipeline.addLast("unpack", new Unpack104Handler());
-		// 数据检查工具
-		pipeline.addLast("check", new Check104Handler());
-//		/拦截 U帧处理器 
-		pipeline.addLast("uframe", new SysUframeClientHandler());
-		//拦截 S帧处理器 
-		pipeline.addLast("sframe", new SysSframeHandler());
-		//编码器
-		pipeline.addLast("byteencoder", new BytesEncoder());
-		//编码器
-		pipeline.addLast("encoder", new DataEncoder());
+    private Iec104Config iec104Config;
 
-		//解码器
-		pipeline.addLast("decoder", new DataDecoder());
-		pipeline.addLast("handler", new Iec104ClientHandler(dataHandler));
-	}
+    /**
+     * 初始化处理链
+     */
+    @Override
+    public void initChannel(SocketChannel ch) {
+        if (iec104Config == null) {
+            Iec104ThreadLocal.setIec104Config(iec104Config);
+        } else {
+            Iec104ThreadLocal.setIec104Config(new DefaultIec104Config());
+        }
+        ChannelPipeline pipeline = ch.pipeline();
+        // 沾包拆包工具
+        pipeline.addLast("unpack", new Unpack104Handler());
+        // 数据检查工具
+        pipeline.addLast("check", new Check104Handler());
+        // 拦截 U帧处理器
+        pipeline.addLast("uframe", new SysUframeClientHandler());
+        // 拦截 S帧处理器
+        pipeline.addLast("sframe", new SysSframeHandler());
+        // 编码器
+        pipeline.addLast("byteencoder", new BytesEncoder());
+        // 编码器
+        pipeline.addLast("encoder", new DataEncoder());
+
+        //解码器
+        pipeline.addLast("decoder", new DataDecoder());
+        pipeline.addLast("handler", new Iec104ClientHandler(dataHandler));
+    }
 }

+ 18 - 3
platform-iec/src/main/java/com/ydl/iec/iec104/server/master/Iec104TcpClientMaster.java

@@ -6,6 +6,7 @@ import com.ydl.iec.iec104.server.Iec104Master;
 import com.ydl.iec.iec104.server.handler.DataHandler;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelOption;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
@@ -31,16 +32,30 @@ public class Iec104TcpClientMaster implements Iec104Master {
 	}
 
 	@Override
-	public void run() throws Exception {
+	public void run() {
 		EventLoopGroup bossGroup = new NioEventLoopGroup();
+		try{
 	    Bootstrap bs = new Bootstrap();
 	    bs.group(bossGroup)
 	      .channel(NioSocketChannel.class)
 	      .option(ChannelOption.SO_KEEPALIVE, true)
 	      .handler(new Iec104ClientInitializer().setDataHandler(dataHandler).setIec104Config(iec104Config));
 	    // 客户端开启
-	    Channel channel  = bs.connect(host, port).sync().channel();
-	    channel.closeFuture().sync();
+		ChannelFuture channelFuture = bs.connect(host, port);
+		channelFuture.addListener(new ConnectionListener());
+		Channel channel  = channelFuture.sync().channel();
+	   	channel.closeFuture().sync();
+		}catch (Exception e){
+			e.printStackTrace();
+		}finally {
+			// 注意,不能管理线程组,因为在循环重连,关闭后,导致无法重连
+			//关闭线程组
+			/*try {
+				bossGroup.shutdownGracefully().sync();
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}*/
+		}
 	}
 
 	@Override

+ 28 - 21
platform-iec/src/main/java/com/ydl/iec/iec104/server/master/handler/Iec104ClientHandler.java

@@ -6,12 +6,16 @@ import com.ydl.iec.iec104.core.ControlManageUtil;
 import com.ydl.iec.iec104.core.Iec104ThreadLocal;
 import com.ydl.iec.iec104.core.ScheduledTaskPool;
 import com.ydl.iec.iec104.message.MessageDetail;
+import com.ydl.iec.iec104.server.Iec104MasterFactory;
 import com.ydl.iec.iec104.server.handler.ChannelHandlerImpl;
 import com.ydl.iec.iec104.server.handler.DataHandler;
+import com.ydl.iec.util.Iec104Util;
 import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.EventLoop;
 import io.netty.channel.SimpleChannelInboundHandler;
 
 import java.io.IOException;
+import java.util.concurrent.TimeUnit;
 
 public class Iec104ClientHandler extends SimpleChannelInboundHandler<MessageDetail> {
 
@@ -23,7 +27,7 @@ public class Iec104ClientHandler extends SimpleChannelInboundHandler<MessageDeta
 	
 	
 	@Override
-	public void channelActive(ChannelHandlerContext ctx) throws Exception {
+	public void channelActive(ChannelHandlerContext ctx)  {
 		// 启动成功后一直发启动链路命令
 		Iec104ThreadLocal.setScheduledTaskPool(new ScheduledTaskPool(ctx));
 		Iec104ThreadLocal.getScheduledTaskPool().sendStatrFrame();
@@ -31,14 +35,11 @@ public class Iec104ClientHandler extends SimpleChannelInboundHandler<MessageDeta
 		Iec104ThreadLocal.getControlPool().startSendFrameTask();
 
 		if (dataHandler != null) {
-			CachedThreadPool.getCachedThreadPool().execute(new Runnable() {
-				@Override
-				public void run() {
-					try {
-						dataHandler.handlerAdded(new ChannelHandlerImpl(ctx));
-					} catch (Exception e) {
-						e.printStackTrace();
-					}
+			CachedThreadPool.getCachedThreadPool().execute(() -> {
+				try {
+					dataHandler.handlerAdded(new ChannelHandlerImpl(ctx));
+				} catch (Exception e) {
+					e.printStackTrace();
 				}
 			});
         }
@@ -47,19 +48,25 @@ public class Iec104ClientHandler extends SimpleChannelInboundHandler<MessageDeta
 	@Override
 	public void channelRead0(ChannelHandlerContext ctx, MessageDetail ruleDetail104) throws IOException {
 		if (dataHandler != null) {
-			CachedThreadPool.getCachedThreadPool().execute(new Runnable() {
-    			@Override
-    			public void run() {
-    				try {
-						dataHandler.channelRead(new ChannelHandlerImpl(ctx), ruleDetail104);
-					} catch (Exception e) {
-						// TODO Auto-generated catch block
-						e.printStackTrace();
-					}
-    			}
-    		});
+			CachedThreadPool.getCachedThreadPool().execute(() -> {
+				try {
+					dataHandler.channelRead(new ChannelHandlerImpl(ctx), ruleDetail104);
+				} catch (Exception e) {
+					// TODO Auto-generated catch block
+					e.printStackTrace();
+				}
+			});
     	}
 	}
 
-
+	@Override
+	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
+		System.err.println("掉线了...");
+		//使用过程中断线重连
+		final EventLoop eventLoop = ctx.channel().eventLoop();
+		eventLoop.schedule((Runnable) () -> {
+			Iec104MasterFactory.createTcpClientMaster(Iec104Util.host, Iec104Util.port).run();
+		}, 5L, TimeUnit.SECONDS);
+		super.channelInactive(ctx);
+	}
 }

+ 2 - 0
platform-iec/src/main/java/com/ydl/iec/util/Iec104Util.java

@@ -14,6 +14,8 @@ import com.ydl.iec.iec104.enums.UControlEnum;
 public class Iec104Util {
 	
 	private static int controlLength = 4;
+	public static int port = 2404;
+	public static String host = "127.0.0.1";
 	
 	/**
 	 * I 格式 低位在前