Selaa lähdekoodia

初始化提交

luoguangyi 3 vuotta sitten
vanhempi
commit
db0ef15424
78 muutettua tiedostoa jossa 8479 lisäystä ja 10 poistoa
  1. 29 10
      .gitignore
  2. 118 0
      .mvn/wrapper/MavenWrapperDownloader.java
  3. BIN
      .mvn/wrapper/maven-wrapper.jar
  4. 2 0
      .mvn/wrapper/maven-wrapper.properties
  5. 310 0
      mvnw
  6. 182 0
      mvnw.cmd
  7. 157 0
      pom.xml
  8. 15 0
      src/main/java/com/persagy/iottransfer/IotTransferApplication.java
  9. 53 0
      src/main/java/com/persagy/iottransfer/client/IotClient.java
  10. 69 0
      src/main/java/com/persagy/iottransfer/client/IotClientReceiveMessageThread.java
  11. 27 0
      src/main/java/com/persagy/iottransfer/communication/entity/Packet.java
  12. 24 0
      src/main/java/com/persagy/iottransfer/communication/entity/PacketEntity.java
  13. 8 0
      src/main/java/com/persagy/iottransfer/communication/entity/UDPSendEntity.java
  14. 66 0
      src/main/java/com/persagy/iottransfer/communication/mina/codec/MinaCodecFactory.java
  15. 96 0
      src/main/java/com/persagy/iottransfer/communication/mina/codec/MinaPacketDecoder.java
  16. 89 0
      src/main/java/com/persagy/iottransfer/communication/mina/codec/MinaPacketEncoder.java
  17. 72 0
      src/main/java/com/persagy/iottransfer/communication/mina/tcp/client/TCPClientIoHandler.java
  18. 428 0
      src/main/java/com/persagy/iottransfer/communication/mina/tcp/client/TCPClientManager.java
  19. 94 0
      src/main/java/com/persagy/iottransfer/communication/mina/tcp/server/TCPServerIoHandler.java
  20. 445 0
      src/main/java/com/persagy/iottransfer/communication/mina/tcp/server/TCPServerManager.java
  21. 72 0
      src/main/java/com/persagy/iottransfer/communication/mina/udp/client/UDPClientIoHandler.java
  22. 216 0
      src/main/java/com/persagy/iottransfer/communication/mina/udp/client/UDPClientManager.java
  23. 88 0
      src/main/java/com/persagy/iottransfer/communication/mina/udp/server/UDPServerIoHandler.java
  24. 199 0
      src/main/java/com/persagy/iottransfer/communication/mina/udp/server/UDPServerManager.java
  25. 92 0
      src/main/java/com/persagy/iottransfer/communication/netty/codec/NettyPacketDecoder.java
  26. 79 0
      src/main/java/com/persagy/iottransfer/communication/netty/codec/NettyPacketEncoder.java
  27. 58 0
      src/main/java/com/persagy/iottransfer/communication/netty/tcp/client/ClientChannelInitializer.java
  28. 66 0
      src/main/java/com/persagy/iottransfer/communication/netty/tcp/client/NettyTCPClientHandler.java
  29. 387 0
      src/main/java/com/persagy/iottransfer/communication/netty/tcp/client/NettyTCPClientManager.java
  30. 90 0
      src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/NettyTCPServerHandler.java
  31. 411 0
      src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/NettyTCPServerManager.java
  32. 49 0
      src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/SSLHandshakeListener.java
  33. 61 0
      src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/ServerChannelInitializer.java
  34. 76 0
      src/main/java/com/persagy/iottransfer/communication/netty/udp/client/NettyUDPClientHandler.java
  35. 226 0
      src/main/java/com/persagy/iottransfer/communication/netty/udp/client/NettyUDPClientManager.java
  36. 73 0
      src/main/java/com/persagy/iottransfer/communication/netty/udp/server/NettyUDPServerHandler.java
  37. 193 0
      src/main/java/com/persagy/iottransfer/communication/netty/udp/server/NettyUDPServerManager.java
  38. 201 0
      src/main/java/com/persagy/iottransfer/communication/nio/tcp/client/NIOTCPClientManager.java
  39. 172 0
      src/main/java/com/persagy/iottransfer/communication/nio/tcp/client/NIOTCPClientThread.java
  40. 219 0
      src/main/java/com/persagy/iottransfer/communication/nio/tcp/server/NIOTCPServerManager.java
  41. 224 0
      src/main/java/com/persagy/iottransfer/communication/nio/tcp/server/NIOTCPServerThread.java
  42. 115 0
      src/main/java/com/persagy/iottransfer/communication/nio/udp/client/NIOUDPClientManager.java
  43. 149 0
      src/main/java/com/persagy/iottransfer/communication/nio/udp/client/NIOUDPClientThread.java
  44. 157 0
      src/main/java/com/persagy/iottransfer/communication/nio/udp/server/NIOUDPServerManager.java
  45. 161 0
      src/main/java/com/persagy/iottransfer/communication/nio/udp/server/NIOUDPServerThread.java
  46. 56 0
      src/main/java/com/persagy/iottransfer/communication/util/AESHelper.java
  47. 182 0
      src/main/java/com/persagy/iottransfer/communication/util/CompressUtil.java
  48. 24 0
      src/main/java/com/persagy/iottransfer/communication/util/ExceptionUtil.java
  49. 41 0
      src/main/java/com/persagy/iottransfer/communication/util/FileToByte.java
  50. 114 0
      src/main/java/com/persagy/iottransfer/communication/util/HexToByte.java
  51. 12 0
      src/main/java/com/persagy/iottransfer/communication/util/IClientHandler.java
  52. 32 0
      src/main/java/com/persagy/iottransfer/communication/util/IClientManager.java
  53. 13 0
      src/main/java/com/persagy/iottransfer/communication/util/ILogger.java
  54. 13 0
      src/main/java/com/persagy/iottransfer/communication/util/IServerHandler.java
  55. 34 0
      src/main/java/com/persagy/iottransfer/communication/util/IServerManager.java
  56. 157 0
      src/main/java/com/persagy/iottransfer/communication/util/MyDecoder.java
  57. 152 0
      src/main/java/com/persagy/iottransfer/communication/util/MyEncoder.java
  58. 92 0
      src/main/java/com/persagy/iottransfer/communication/util/MySslContextFactory.java
  59. 118 0
      src/main/java/com/persagy/iottransfer/communication/util/MyStream.java
  60. 46 0
      src/main/java/com/persagy/iottransfer/communication/util/PacketBuffer.java
  61. 30 0
      src/main/java/com/persagy/iottransfer/config/CollectServerProperties.java
  62. 30 0
      src/main/java/com/persagy/iottransfer/config/ControlServerProperties.java
  63. 48 0
      src/main/java/com/persagy/iottransfer/config/IotProperties.java
  64. 119 0
      src/main/java/com/persagy/iottransfer/config/KafkaCommonConfig.java
  65. 37 0
      src/main/java/com/persagy/iottransfer/config/ProjectClent.java
  66. 39 0
      src/main/java/com/persagy/iottransfer/init/DaemonThread.java
  67. 351 0
      src/main/java/com/persagy/iottransfer/init/alibabaiotgateway.java
  68. 54 0
      src/main/java/com/persagy/iottransfer/kafka/KafkaConsumerCloud2Edge.java
  69. 68 0
      src/main/java/com/persagy/iottransfer/kafka/KafkaConsumerEdge2Cloud.java
  70. 73 0
      src/main/java/com/persagy/iottransfer/kafka/KafkaProducer.java
  71. 43 0
      src/main/java/com/persagy/iottransfer/kafka/KafkaServerMessageReceiver.java
  72. 57 0
      src/main/java/com/persagy/iottransfer/server/IotServer.java
  73. 75 0
      src/main/java/com/persagy/iottransfer/server/IotServerReceiveMessageThread.java
  74. 1 0
      src/main/resources/application.properties
  75. 122 0
      src/main/resources/application.yml
  76. 20 0
      src/main/resources/log4j.properties
  77. 95 0
      src/main/resources/logback-spring.xml
  78. 13 0
      src/test/java/com/persagy/iottransfer/IotTransferApplicationTests.java

+ 29 - 10
.gitignore

@@ -1,14 +1,33 @@
-# ---> Java
-*.class
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
 
-# Mobile Tools for Java (J2ME)
-.mtj.tmp/
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
 
-# Package Files #
-*.jar
-*.war
-*.ear
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
 
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
 
+### VS Code ###
+.vscode/

+ 118 - 0
.mvn/wrapper/MavenWrapperDownloader.java

@@ -0,0 +1,118 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+    private static final String WRAPPER_VERSION = "0.5.6";
+    /**
+     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+     */
+    private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+            + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+    /**
+     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+     * use instead of the default one.
+     */
+    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+            ".mvn/wrapper/maven-wrapper.properties";
+
+    /**
+     * Path where the maven-wrapper.jar will be saved to.
+     */
+    private static final String MAVEN_WRAPPER_JAR_PATH =
+            ".mvn/wrapper/maven-wrapper.jar";
+
+    /**
+     * Name of the property which should be used to override the default download url for the wrapper.
+     */
+    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+    public static void main(String args[]) {
+        System.out.println("- Downloader started");
+        File baseDirectory = new File(args[0]);
+        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+        // If the maven-wrapper.properties exists, read it and check if it contains a custom
+        // wrapperUrl parameter.
+        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+        String url = DEFAULT_DOWNLOAD_URL;
+        if (mavenWrapperPropertyFile.exists()) {
+            FileInputStream mavenWrapperPropertyFileInputStream = null;
+            try {
+                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+                Properties mavenWrapperProperties = new Properties();
+                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+            } catch (IOException e) {
+                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+            } finally {
+                try {
+                    if (mavenWrapperPropertyFileInputStream != null) {
+                        mavenWrapperPropertyFileInputStream.close();
+                    }
+                } catch (IOException e) {
+                    // Ignore ...
+                }
+            }
+        }
+        System.out.println("- Downloading from: " + url);
+
+        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+        if (!outputFile.getParentFile().exists()) {
+            if (!outputFile.getParentFile().mkdirs()) {
+                System.out.println(
+                        "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+            }
+        }
+        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+        try {
+            downloadFileFromURL(url, outputFile);
+            System.out.println("Done");
+            System.exit(0);
+        } catch (Throwable e) {
+            System.out.println("- Error downloading");
+            e.printStackTrace();
+            System.exit(1);
+        }
+    }
+
+    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+        if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+            String username = System.getenv("MVNW_USERNAME");
+            char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+            Authenticator.setDefault(new Authenticator() {
+                @Override
+                protected PasswordAuthentication getPasswordAuthentication() {
+                    return new PasswordAuthentication(username, password);
+                }
+            });
+        }
+        URL website = new URL(urlString);
+        ReadableByteChannel rbc;
+        rbc = Channels.newChannel(website.openStream());
+        FileOutputStream fos = new FileOutputStream(destination);
+        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+        fos.close();
+        rbc.close();
+    }
+
+}

BIN
.mvn/wrapper/maven-wrapper.jar


+ 2 - 0
.mvn/wrapper/maven-wrapper.properties

@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.2/apache-maven-3.8.2-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar

+ 310 - 0
mvnw

@@ -0,0 +1,310 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
+    fi
+else
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
+    fi
+    if [ -n "$MVNW_REPOURL" ]; then
+      jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    else
+      jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    fi
+    while IFS="=" read key value; do
+      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
+      esac
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
+    if [ "$MVNW_VERBOSE" = true ]; then
+      echo "Downloading from: $jarUrl"
+    fi
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
+    if $cygwin; then
+      wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
+    fi
+
+    if command -v wget > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found wget ... using wget"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget "$jarUrl" -O "$wrapperJarPath"
+        else
+            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Found curl ... using curl"
+        fi
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl -o "$wrapperJarPath" "$jarUrl" -f
+        else
+            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
+        fi
+
+    else
+        if [ "$MVNW_VERBOSE" = true ]; then
+          echo "Falling back to using Java to download"
+        fi
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaClass=`cygpath --path --windows "$javaClass"`
+        fi
+        if [ -e "$javaClass" ]; then
+            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Compiling MavenWrapperDownloader.java ..."
+                fi
+                # Compiling the Java class
+                ("$JAVA_HOME/bin/javac" "$javaClass")
+            fi
+            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
+                # Running the downloader
+                if [ "$MVNW_VERBOSE" = true ]; then
+                  echo " - Running MavenWrapperDownloader.java ..."
+                fi
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+if [ "$MVNW_VERBOSE" = true ]; then
+  echo $MAVEN_PROJECTBASEDIR
+fi
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 182 - 0
mvnw.cmd

@@ -0,0 +1,182 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    https://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM set title of command window
+title %0
+@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+
+FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
+    IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
+)
+
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
+if exist %WRAPPER_JAR% (
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Found %WRAPPER_JAR%
+    )
+) else (
+    if not "%MVNW_REPOURL%" == "" (
+        SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
+    )
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Couldn't find %WRAPPER_JAR%, downloading it ...
+        echo Downloading from: %DOWNLOAD_URL%
+    )
+
+    powershell -Command "&{"^
+		"$webclient = new-object System.Net.WebClient;"^
+		"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
+		"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
+		"}"^
+		"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
+		"}"
+    if "%MVNW_VERBOSE%" == "true" (
+        echo Finished downloading %WRAPPER_JAR%
+    )
+)
+@REM End of extension
+
+@REM Provide a "standardized" way to retrieve the CLI args that will
+@REM work with both Windows and non-Windows executions.
+set MAVEN_CMD_LINE_ARGS=%*
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%

+ 157 - 0
pom.xml

@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.3.1.RELEASE</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.persagy</groupId>
+    <artifactId>iot-transfer</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>iot-transfer</name>
+    <description>Demo project for Spring Boot</description>
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>SagaCloud</id>
+            <name>SagaCloud</name>
+            <url>http://47.93.33.207:8082/repository/SagaCloud/</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <releases>
+                <enabled>true</enabled>
+            </releases>
+        </repository>
+        <repository>
+            <id>alimaven</id>
+            <name>aliyun maven</name>
+            <url>http://maven.aliyun.com/nexus/content/groups/public</url>
+        </repository>
+        <repository>
+            <id>mvnrepository</id>
+            <url>https://mvnrepository.com/</url>
+        </repository>
+        <repository>
+            <id>sonatype-nexus-snapshots</id>
+            <name>Sonatype Nexus Snapshots</name>
+            <url>http://oss.sonatype.org/content/repositories/snapshots</url>
+        </repository>
+        <repository>
+            <id>spring-milestones</id>
+            <name>Spring Milestones</name>
+            <url>https://repo.spring.io/milestone</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.kafka</groupId>
+            <artifactId>spring-kafka</artifactId>
+            <version>2.3.4.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-log4j</artifactId>
+            <version>1.3.8.RELEASE</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.7.9</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.78</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.mina</groupId>
+            <artifactId>mina-core</artifactId>
+            <version>2.0.7</version>
+        </dependency>
+        <!-- netty -->
+        <dependency>
+            <groupId>io.netty</groupId>
+            <artifactId>netty-all</artifactId>
+            <version>4.1.62.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <!-- amqp 1.0 qpid client -->
+        <dependency>
+            <groupId>org.apache.qpid</groupId>
+            <artifactId>qpid-jms-client</artifactId>
+            <version>0.56.0</version>
+        </dependency>
+        <!--alibaba http2 -->
+        <dependency>
+            <groupId>com.aliyun.openservices</groupId>
+            <artifactId>iot-client-message</artifactId>
+            <version>1.1.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>aliyun-java-sdk-core</artifactId>
+            <version>3.7.1</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.1</version>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+    <distributionManagement>
+        <repository>
+            <id>SagaCloudRelease</id>
+            <name>User Project Release</name>
+            <url>http://47.93.33.207:8082/repository/SagaCloudRelease/</url>
+        </repository>
+
+        <snapshotRepository>
+            <id>SagaCloudRelease</id>
+            <name>User Project SNAPSHOTS</name>
+            <url>http://47.93.33.207:8082/repository/SagaCloudSnapshot/</url>
+        </snapshotRepository>
+    </distributionManagement>
+</project>

+ 15 - 0
src/main/java/com/persagy/iottransfer/IotTransferApplication.java

@@ -0,0 +1,15 @@
+package com.persagy.iottransfer;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.web.servlet.ServletComponentScan;
+
+@SpringBootApplication
+@ServletComponentScan
+public class IotTransferApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(IotTransferApplication.class, args);
+    }
+
+}

+ 53 - 0
src/main/java/com/persagy/iottransfer/client/IotClient.java

@@ -0,0 +1,53 @@
+package com.persagy.iottransfer.client;
+
+import com.persagy.iottransfer.communication.mina.tcp.client.TCPClientManager;
+import com.persagy.iottransfer.communication.mina.udp.client.UDPClientManager;
+import com.persagy.iottransfer.communication.util.IClientManager;
+import com.persagy.iottransfer.config.IotProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/26 15:18
+ */
+@Service
+public class IotClient {
+    //项目ID和clientManager映射
+    public static final Map<String,IClientManager> clientproject2CollectManagerMap = new ConcurrentHashMap<>();
+    public static final Map<String,IClientManager> clientproject2ControlManagerMap = new ConcurrentHashMap<>();
+    @Autowired
+    IotProperties iotProperties;
+
+
+    public void init() {
+        for (IotProperties.Client client : iotProperties.getClients()) {
+            for (IotProperties.Project project : iotProperties.projects) {
+                //String address = "/" +project.getId()+ ":" + client.getTarget_ip() + ":" + client.getTarget_port();
+                IClientManager clientManager;
+                if ("UDP".equalsIgnoreCase(client.getProtocol())) {
+                    clientManager = UDPClientManager.builder().targetIp(client.getTarget_ip()).targetPort(client.getTarget_port()).encoding("utf-8").compress(client.getCompress()).Max_size(client.getMax_size()).projectId(project.getId()).client(client).build();
+                } else {
+                    clientManager = TCPClientManager.builder().ip(client.getTarget_ip()).port(client.getTarget_port()).encoding("utf-8").compress(client.getCompress()).Max_size(client.getMax_size()).projectId(project.getId()).client(client)
+                    .separate(true).separateBytes(false).prefix((byte) client.getSeparate_begin().charAt(0)).suffix((byte) client.getSeparate_end().charAt(0)).build();
+                }
+                clientManager.hasRemark(100);
+                clientManager.Start();
+                if(client.getServer_is_iot_collect()){
+                    clientproject2CollectManagerMap.put(project.getId(),clientManager);
+                }
+                if(client.getServer_is_iot_control()){
+                    clientproject2ControlManagerMap.put(project.getId(),clientManager);
+                }
+            }
+
+        }
+
+    }
+
+
+}

+ 69 - 0
src/main/java/com/persagy/iottransfer/client/IotClientReceiveMessageThread.java

@@ -0,0 +1,69 @@
+package com.persagy.iottransfer.client;
+
+import cn.hutool.core.thread.ThreadUtil;
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.util.IClientManager;
+import com.persagy.iottransfer.kafka.KafkaProducer;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+
+/**
+ * @description: AlarmMessage消费线程
+ * @author:LuoGuangyi
+ * @company:PersagyTechnologyCo.,Ltd
+ * @since:2021/01/29 17:08
+ * @version:V1.0
+ **/
+@Slf4j
+public class IotClientReceiveMessageThread implements Runnable {
+
+    KafkaProducer kafkaProducer;
+
+    public IotClientReceiveMessageThread(KafkaProducer kafkaProducer) {
+        this.kafkaProducer = kafkaProducer;
+    }
+
+    @Override
+    public void run() {
+        try {
+            System.out.println("--init IotClientReceiveMessageThread start--");
+            for (Map.Entry<String, IClientManager> entry : IotClient.clientproject2CollectManagerMap.entrySet()) {
+
+                ThreadUtil.execAsync(()->{
+                    while (true){
+                        try {
+                            Packet packet = entry.getValue().takeRece();
+                            String project = entry.getKey();
+                            PacketEntity packetEntity = new PacketEntity(project,packet);
+                            kafkaProducer.sendFromcollect2edge(packetEntity);
+                        } catch (Exception e) {
+                            log.error(e.getMessage(),e);
+                        }
+                    }
+                },true);
+
+            }
+            for (Map.Entry<String, IClientManager> entry : IotClient.clientproject2ControlManagerMap.entrySet()) {
+                ThreadUtil.execAsync(()->{
+                    while (true){
+                        try {
+                            Packet packet = entry.getValue().takeRece();
+                            String project = entry.getKey();
+                            PacketEntity packetEntity = new PacketEntity(project,packet);
+                            kafkaProducer.sendFromcontrol2edge(packetEntity);
+                        } catch (Exception e) {
+                            log.error(e.getMessage(),e);
+                        }
+                    }
+                },true);
+
+            }
+            System.out.println("--init IotClientReceiveMessageThread end--");
+        } catch (Exception e) {
+            log.error("消息处理失败", e);
+        }
+    }
+
+}

+ 27 - 0
src/main/java/com/persagy/iottransfer/communication/entity/Packet.java

@@ -0,0 +1,27 @@
+package com.persagy.iottransfer.communication.entity;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+@Data
+@NoArgsConstructor
+public class Packet {
+    public String packetString;
+    public byte[] packetBytes;
+    public Date time = new Date();
+
+    public Packet(String packetString) {
+        this.packetString = packetString;
+    }
+
+    public Packet(byte[] packetBytes) {
+        this.packetBytes = packetBytes;
+    }
+
+    @Override
+    public String toString() {
+        return JSONObject.toJSONString(this);
+    }
+}

+ 24 - 0
src/main/java/com/persagy/iottransfer/communication/entity/PacketEntity.java

@@ -0,0 +1,24 @@
+package com.persagy.iottransfer.communication.entity;
+
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+public class PacketEntity {
+    public String address;
+    public String projectId;
+    public String type;
+    public Packet content;
+
+    public PacketEntity(String projectId, Packet content) {
+        this.projectId = projectId;
+        this.content = content;
+    }
+
+    @Override
+    public String toString() {
+        return JSONObject.toJSONString(this);
+    }
+}

+ 8 - 0
src/main/java/com/persagy/iottransfer/communication/entity/UDPSendEntity.java

@@ -0,0 +1,8 @@
+package com.persagy.iottransfer.communication.entity;
+
+import java.net.SocketAddress;
+
+public class UDPSendEntity {
+    public SocketAddress address;
+    public Packet content;
+}

+ 66 - 0
src/main/java/com/persagy/iottransfer/communication/mina/codec/MinaCodecFactory.java

@@ -0,0 +1,66 @@
+package com.persagy.iottransfer.communication.mina.codec;
+
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+import java.util.List;
+
+public class MinaCodecFactory implements ProtocolCodecFactory {
+    private final ProtocolEncoder encoder;
+    private final ProtocolDecoder decoder;
+
+    public MinaCodecFactory(String ip, int port, String encoding, String aes_password, boolean compress) {
+        encoder = new MinaPacketEncoder(ip, port, encoding, aes_password, compress);
+        decoder = new MinaPacketDecoder(ip, port, encoding, aes_password, compress);
+    }
+
+    public MinaCodecFactory(String ip, int port, String encoding, String aes_password, boolean compress, byte prefix,
+                            byte suffix) {
+        encoder = new MinaPacketEncoder(ip, port, encoding, aes_password, compress, prefix, suffix);
+        decoder = new MinaPacketDecoder(ip, port, encoding, aes_password, compress, prefix, suffix);
+    }
+
+    public MinaCodecFactory(String ip, int port, String encoding, String aes_password, boolean compress,
+                            byte[] prefixBytes, byte[] suffixBytes) {
+        encoder = new MinaPacketEncoder(ip, port, encoding, aes_password, compress, prefixBytes, suffixBytes);
+        decoder = new MinaPacketDecoder(ip, port, encoding, aes_password, compress, prefixBytes, suffixBytes);
+    }
+
+    public static void add_forbit_byte(byte b, List<Byte> byteList) {
+        boolean exist = false;
+        for (Byte bb : byteList) {
+            if (bb == b) {
+                exist = true;
+                break;
+            }
+        }
+        if (!exist) {
+            byteList.add(b);
+        }
+    }
+
+    public static void add_forbit_bytes(byte[] bytes, List<Byte> byteList) {
+        for (byte b : bytes) {
+            boolean exist = false;
+            for (Byte bb : byteList) {
+                if (bb == b) {
+                    exist = true;
+                    break;
+                }
+            }
+            if (!exist) {
+                byteList.add(b);
+            }
+        }
+    }
+
+    public ProtocolEncoder getEncoder(IoSession ioSession) throws Exception {
+        return encoder;
+    }
+
+    public ProtocolDecoder getDecoder(IoSession ioSession) throws Exception {
+        return decoder;
+    }
+}

+ 96 - 0
src/main/java/com/persagy/iottransfer/communication/mina/codec/MinaPacketDecoder.java

@@ -0,0 +1,96 @@
+package com.persagy.iottransfer.communication.mina.codec;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.MyDecoder;
+import org.apache.mina.core.buffer.IoBuffer;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MinaPacketDecoder extends CumulativeProtocolDecoder {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+
+    boolean separate = false;
+    boolean separateBytes = false;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    MyDecoder decoder;
+    Map<String, List<Byte>> tmpByteListMap = new HashMap<String, List<Byte>>();
+
+    public MinaPacketDecoder(String ip, int port, String encoding, String aes_password, boolean compress) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+
+        this.separate = false;
+
+        this.decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public MinaPacketDecoder(String ip, int port, String encoding, String aes_password, boolean compress, byte prefix,
+                             byte suffix) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public MinaPacketDecoder(String ip, int port, String encoding, String aes_password, boolean compress,
+                             byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
+        int remainingLength = in.remaining();
+        byte[] remainingBytes = new byte[remainingLength];
+        for (int i = 0; i < remainingLength; i++) {
+            remainingBytes[i] = in.get();
+        }
+
+        String remoteAddress = session.getRemoteAddress().toString();
+        List<Packet> packetList = this.decoder.decode(remoteAddress, remainingBytes);
+        for (int i = 0; i < packetList.size(); i++) {
+            Packet packet = packetList.get(i);
+            out.write(packet);
+        }
+        return true;
+    }
+}

+ 89 - 0
src/main/java/com/persagy/iottransfer/communication/mina/codec/MinaPacketEncoder.java

@@ -0,0 +1,89 @@
+package com.persagy.iottransfer.communication.mina.codec;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.MyEncoder;
+import org.apache.mina.core.buffer.IoBuffer;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+public class MinaPacketEncoder implements ProtocolEncoder {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+
+    boolean separate = false;
+    boolean separateBytes = false;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    MyEncoder encoder;
+
+    public MinaPacketEncoder(String ip, int port, String encoding, String aes_password, boolean compress) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+
+        this.separate = false;
+
+        this.encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public MinaPacketEncoder(String ip, int port, String encoding, String aes_password, boolean compress, byte prefix,
+                             byte suffix) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public MinaPacketEncoder(String ip, int port, String encoding, String aes_password, boolean compress,
+                             byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public synchronized void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+        Packet request = (Packet) message;
+        byte[] comm_bytes = this.encoder.encode(request);
+        int comm_length = comm_bytes.length;
+        IoBuffer buffer = IoBuffer.allocate(comm_length, false);
+        buffer.put(comm_bytes);
+        buffer.flip();
+        out.write(buffer);
+    }
+
+    public void dispose(IoSession session) throws Exception {
+        // nothing to dispose
+    }
+}

+ 72 - 0
src/main/java/com/persagy/iottransfer/communication/mina/tcp/client/TCPClientIoHandler.java

@@ -0,0 +1,72 @@
+package com.persagy.iottransfer.communication.mina.tcp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+
+@Slf4j
+public class TCPClientIoHandler extends IoHandlerAdapter {
+    TCPClientManager manager;
+
+    public TCPClientIoHandler(TCPClientManager manager) {
+        this.manager = manager;
+    }
+
+    public void sessionCreated(IoSession session) throws Exception {
+        log.info(this.manager.Name() + "\tsessionCreated");
+    }
+
+    public void sessionOpened(IoSession session) throws Exception {
+        this.manager.SetSessionClosed(false);
+        log.warn(this.manager.Name() + "\tsessionOpened");
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionOpened();
+        }
+    }
+
+    public void sessionClosed(IoSession session) throws Exception {
+        this.manager.SetSessionClosed(true);
+        log.warn(this.manager.Name() + "\tsessionClosed");
+        // �쳣�ر�
+        this.manager.Stop();
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionClosed();
+        }
+    }
+
+    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(cause);
+        }
+    }
+
+    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
+        log.warn(this.manager.Name() + "\tsessionIdle");
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionIdle();
+        }
+        session.close(true);
+    }
+
+    public void messageReceived(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        this.manager.AppendToRece(packet);
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\trece\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\trece\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+
+    public void messageSent(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\tsend\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\tsend\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+}

+ 428 - 0
src/main/java/com/persagy/iottransfer/communication/mina/tcp/client/TCPClientManager.java

@@ -0,0 +1,428 @@
+package com.persagy.iottransfer.communication.mina.tcp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.mina.codec.MinaCodecFactory;
+import com.persagy.iottransfer.communication.util.*;
+import com.persagy.iottransfer.config.IotProperties;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.future.ConnectFuture;
+import org.apache.mina.core.service.IoConnector;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.transport.socket.nio.NioSocketConnector;
+
+import java.net.InetSocketAddress;
+
+@Slf4j
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TCPClientManager implements IClientManager {
+    String projectId;
+    IotProperties.Client client;
+    String ip;
+    int port;
+    String encoding;
+    String ssl_protocol;
+    String ssl_keystoretype;
+    String ssl_algorithm;
+    byte[] ssl_file_km;
+    String ssl_password_km;
+    byte[] ssl_file_tm;
+    String ssl_password_tm;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    boolean separate;
+    boolean separateBytes;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    Integer IdleTime = null;
+
+    boolean sessionClosed = false;
+
+    IClientHandler handlerManager;
+    ILogger logger;
+
+    public final PacketBuffer<Packet> receList = new PacketBuffer<Packet>();
+
+    IoSession session;
+    IoConnector connector;
+    String localAddress = "()";
+    int remark_count = 0;
+
+    public TCPClientManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, int Max_size, byte[] prefixBytes,
+                            byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size, byte prefix,
+                            byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size, byte[] prefixBytes,
+                            byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+        this.separateBytes = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                            byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                            byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                            Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+        this.separateBytes = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                            Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                            Integer IdleTime, int Max_size, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                            String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                            String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+        this.separateBytes = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                            String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                            String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPClientManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                            String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                            String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte[] prefixBytes,
+                            byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public void setHandlerManager(IClientHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    @Override
+    public String getProjectId() {
+        return this.projectId;
+    }
+    @Override
+    public IotProperties.Client getClient() {
+        return this.client;
+    }
+    public String Name() {
+        return "TCP Client " + this.ip + ":" + this.port + localAddress;
+    }
+
+    public synchronized boolean IsSessionClosed() {
+        return this.sessionClosed;
+    }
+
+    public synchronized void SetSessionClosed(boolean value) {
+        this.sessionClosed = value;
+    }
+
+    public synchronized void Start() {
+        if (this.session == null) {
+            try {
+                IoConnector connectorInner = new NioSocketConnector();
+                ProtocolCodecFactory factory;
+                if (this.separate) {
+                    if (this.separateBytes) {
+                        factory = new MinaCodecFactory(this.ip, this.port, this.encoding, this.aes_password,
+                                this.compress, this.prefixBytes, this.suffixBytes);
+                    } else {
+                        factory = new MinaCodecFactory(this.ip, this.port, this.encoding, this.aes_password,
+                                this.compress, this.prefix, this.suffix);
+                    }
+                } else {
+                    factory = new MinaCodecFactory(this.ip, this.port, this.encoding, this.aes_password, this.compress);
+                }
+                if (this.ssl_file_km != null || this.ssl_file_tm != null) {
+                    SslFilter sslFilter = new SslFilter(
+                            MySslContextFactory.getContext(this.ssl_protocol, this.ssl_keystoretype, this.ssl_algorithm,
+                                    this.ssl_file_km, this.ssl_file_tm, this.ssl_password_km, this.ssl_password_tm));
+                    sslFilter.setUseClientMode(true);
+                    connectorInner.getFilterChain().addFirst("sslFilter", sslFilter);
+                }
+                connectorInner.getFilterChain().addLast("codec", new ProtocolCodecFilter(factory));
+                connectorInner.setHandler(new TCPClientIoHandler(this));
+                if (this.IdleTime != null) {
+                    connectorInner.getSessionConfig().setBothIdleTime(this.IdleTime);
+                }
+
+                ConnectFuture connectFuture = connectorInner.connect(new InetSocketAddress(this.ip, this.port));
+                connectFuture.awaitUninterruptibly();
+                if (connectFuture.isDone()) {
+                    if (connectFuture.isConnected()) {
+                        this.session = connectFuture.getSession();
+                        this.localAddress = "(" + this.session.getLocalAddress().toString() + ")";
+                        this.connector = connectorInner;
+                    } else {
+                        connectorInner.dispose();
+                        throw new Exception();
+                    }
+                } else {
+                    connectorInner.dispose();
+                    throw new Exception();
+                }
+
+                log.warn(this.Name() + "\tStart");
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+            }
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new Packet(), Integer.MAX_VALUE);
+        }
+        if (this.session != null) {
+            // CloseFuture closeFuture = this.session.close(true);
+            // closeFuture.awaitUninterruptibly();
+            this.session.close(true);
+            this.session = null;
+
+            this.connector.dispose();
+            this.connector = null;
+        }
+    }
+
+    public void AppendToSend(Packet MyPackage) {
+        if (this.session == null) {
+            this.Start();
+        }
+        if (this.session != null) {
+            this.session.write(MyPackage);
+        }
+    }
+
+    public void AppendToRece(Packet MyPackage) {
+        this.receList.offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopRece() {
+        Packet MyPackage = this.receList.poll();
+        return MyPackage;
+    }
+
+    public Packet takeRece() throws InterruptedException {
+        Packet MyPackage = this.receList.take();
+        return MyPackage;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+
+}

+ 94 - 0
src/main/java/com/persagy/iottransfer/communication/mina/tcp/server/TCPServerIoHandler.java

@@ -0,0 +1,94 @@
+package com.persagy.iottransfer.communication.mina.tcp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import com.persagy.iottransfer.config.IotProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+
+import java.net.SocketAddress;
+import java.util.Date;
+
+@Slf4j
+public class TCPServerIoHandler extends IoHandlerAdapter {
+    TCPServerManager manager;
+
+    public TCPServerIoHandler(TCPServerManager manager) {
+        this.manager = manager;
+    }
+    public void sessionCreated(IoSession session) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        log.info(this.manager.Name() + "\tsessionCreated\t" + remoteAddress);
+    }
+
+    public void sessionOpened(IoSession session) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        this.manager.SetConnectTime(remoteAddress, new Date());
+        if (!this.manager.socketMap.containsKey(remoteAddress)) {
+            this.manager.socketMap.put(remoteAddress, session);
+        }
+        log.warn(this.manager.Name() + "\tsessionOpened\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionOpened(session.getRemoteAddress());
+        }
+    }
+
+    public void sessionClosed(IoSession session) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        this.manager.SetConnectTime(remoteAddress, null);
+        this.manager.socketMap.remove(remoteAddress);
+        log.warn(this.manager.Name() + "\tsessionClosed\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionClosed(session.getRemoteAddress());
+        }
+    }
+
+    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(session.getRemoteAddress(), cause);
+        }
+    }
+
+    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        log.warn(this.manager.Name() + "\tsessionIdle\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionIdle(session.getRemoteAddress());
+        }
+        session.close(true);
+    }
+
+    public void messageReceived(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        SocketAddress socketAddress = session.getRemoteAddress();
+        this.manager.AppendToRece(socketAddress.toString(), packet);
+        try {
+            getProject(packet.packetString,socketAddress);
+        } catch (Exception e) {
+            log.error(e.getMessage(),e);
+        }
+    }
+    public  void getProject(String message,SocketAddress socketAddress){
+        if(this.manager.project2IoSessionMap.containsKey(message.substring(0,10))){
+            return;
+        }
+        this.manager.project2IoSessionMap.put(message.substring(0,10),socketAddress.toString());
+    }
+
+    public void messageSent(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        SocketAddress socketAddress = session.getRemoteAddress();
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\tsend\t" + socketAddress.toString() + "\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\tsend\t" + socketAddress.toString()
+                    + "\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+}

+ 445 - 0
src/main/java/com/persagy/iottransfer/communication/mina/tcp/server/TCPServerManager.java

@@ -0,0 +1,445 @@
+package com.persagy.iottransfer.communication.mina.tcp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.mina.codec.MinaCodecFactory;
+import com.persagy.iottransfer.communication.util.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.filter.ssl.SslFilter;
+import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
+
+import java.net.InetSocketAddress;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TCPServerManager implements IServerManager {
+    String ip;
+    int port;
+    String encoding;
+    String ssl_protocol;
+    String ssl_keystoretype;
+    String ssl_algorithm;
+    byte[] ssl_file_km;
+    String ssl_password_km;
+    byte[] ssl_file_tm;
+    String ssl_password_tm;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    boolean separate;
+    boolean separateBytes;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    Integer IdleTime = null;
+
+    IServerHandler handlerManager;
+    ILogger logger;
+
+    public final Map<String, Date> connectDateMap = new HashMap<String, Date>();
+    public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+
+    NioSocketAcceptor acceptor;
+    //address-IoSession
+    public final Map<String, IoSession> socketMap = new HashMap<String, IoSession>();
+    //project-address
+    public final Map<String, String> project2IoSessionMap = new HashMap<String, String>();
+    int remark_count = 0;
+
+    public TCPServerManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, int Max_size, byte[] prefixBytes,
+                            byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size, byte prefix,
+                            byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size, byte[] prefixBytes,
+                            byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                            byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                            byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                            Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                            Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                            Integer IdleTime, int Max_size, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                            String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                            String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                            String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                            String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public TCPServerManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                            String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                            String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte[] prefixBytes,
+                            byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public void setHandlerManager(IServerHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    public String Name() {
+        return "TCP Server " + this.ip + ":" + this.port;
+    }
+
+    public synchronized void Start() {
+        if (this.acceptor == null) {
+            try {
+                NioSocketAcceptor acceptorInner = new NioSocketAcceptor();
+                ProtocolCodecFactory factory;
+                if (this.separate) {
+                    if (this.separateBytes) {
+                        factory = new MinaCodecFactory(this.ip, this.port, this.encoding, this.aes_password,
+                                this.compress, this.prefixBytes, this.suffixBytes);
+                    } else {
+                        factory = new MinaCodecFactory(this.ip, this.port, this.encoding, this.aes_password,
+                                this.compress, this.prefix, this.suffix);
+                    }
+                } else {
+                    factory = new MinaCodecFactory(this.ip, this.port, this.encoding, this.aes_password, this.compress);
+                }
+                if (this.ssl_file_km != null || this.ssl_file_tm != null) {
+                    SslFilter sslFilter = new SslFilter(
+                            MySslContextFactory.getContext(this.ssl_protocol, this.ssl_keystoretype, this.ssl_algorithm,
+                                    this.ssl_file_km, this.ssl_file_tm, this.ssl_password_km, this.ssl_password_tm));
+                    sslFilter.setUseClientMode(false);
+                    if (this.ssl_file_tm != null) {
+                        sslFilter.setNeedClientAuth(true);
+                    }
+                    acceptorInner.getFilterChain().addFirst("sslFilter", sslFilter);
+                }
+                acceptorInner.getFilterChain().addLast("protocol", new ProtocolCodecFilter(factory));
+                acceptorInner.setHandler(new TCPServerIoHandler(this));
+                acceptorInner.bind(new InetSocketAddress(this.ip, this.port));
+                if (this.IdleTime != null) {
+                    acceptorInner.getSessionConfig().setBothIdleTime(this.IdleTime);
+                }
+
+                this.acceptor = acceptorInner;
+
+                log.warn(this.Name() + "\tStart");
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+            }
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new PacketEntity(), Integer.MAX_VALUE);
+        }
+        if (this.acceptor != null) {
+            // String[] clientAddress_array = this.GetClientAddresss();
+            // for (String clientAddress : clientAddress_array) {
+            // try {
+            // this.closeClient(clientAddress);
+            // } catch (Exception e) {
+            // e.printStackTrace();
+            // }
+            // }
+            this.acceptor.unbind();
+            this.acceptor.dispose();
+            this.acceptor = null;
+        }
+    }
+
+    public synchronized void AllowJustSend_UDP(boolean allow) {
+
+    }
+
+    public synchronized String[] GetClientAddresss() {
+        return this.connectDateMap.keySet().toArray(new String[0]);
+    }
+
+    public synchronized Date GetConnectTime(String clientAddress) {
+        if (this.connectDateMap.containsKey(clientAddress)) {
+            return this.connectDateMap.get(clientAddress);
+        }
+        return null;
+    }
+
+    public synchronized void SetConnectTime(String clientAddress, Date date) {
+        this.connectDateMap.remove(clientAddress);
+        if (date != null) {
+            this.connectDateMap.put(clientAddress, date);
+        }
+    }
+
+    public void AppendToSend(String clientAddress, Packet MyPackage) {
+        IoSession session = this.socketMap.get(clientAddress);
+        if (session != null) {
+            session.write(MyPackage);
+        }
+    }
+    public void AppendToSendByProject(String project, Packet MyPackage) {
+        String clientAddresss = this.project2IoSessionMap.get(project);
+        if(clientAddresss != null){
+            IoSession session = this.socketMap.get(clientAddresss);
+            if (session != null) {
+                session.write(MyPackage);
+            }
+        }
+    }
+    public synchronized boolean ContainsSocket(String clientAddress) {
+        return this.socketMap.containsKey(clientAddress);
+    }
+
+    public void AppendToRece(String clientAddress, Packet MyPackage) {
+        PacketEntity entity = new PacketEntity();
+        entity.address = clientAddress;
+        entity.content = MyPackage;
+        this.receList.offer(entity, this.Max_size);
+    }
+
+    public PacketEntity PopRece() {
+        PacketEntity entity = this.receList.poll();
+        return entity;
+    }
+
+    public PacketEntity takeRece() throws InterruptedException {
+        PacketEntity entity = this.receList.take();
+        return entity;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void closeClient(String clientAddress) {
+        if (this.socketMap.containsKey(clientAddress)) {
+            IoSession session = this.socketMap.get(clientAddress);
+            session.close(true);
+            this.socketMap.remove(clientAddress);
+        }
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 72 - 0
src/main/java/com/persagy/iottransfer/communication/mina/udp/client/UDPClientIoHandler.java

@@ -0,0 +1,72 @@
+package com.persagy.iottransfer.communication.mina.udp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+
+@Slf4j
+public class UDPClientIoHandler extends IoHandlerAdapter {
+    UDPClientManager manager;
+
+    public UDPClientIoHandler(UDPClientManager manager) {
+        this.manager = manager;
+    }
+
+    public void sessionCreated(IoSession session) throws Exception {
+        log.info(this.manager.Name() + "\tsessionCreated");
+    }
+
+    public void sessionOpened(IoSession session) throws Exception {
+        this.manager.SetSessionClosed(false);
+        log.warn(this.manager.Name() + "\tsessionOpened");
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionOpened();
+        }
+    }
+
+    public void sessionClosed(IoSession session) throws Exception {
+        this.manager.SetSessionClosed(true);
+        log.warn(this.manager.Name() + "\tsessionClosed");
+        // �쳣�ر�
+        this.manager.Stop();
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionClosed();
+        }
+    }
+
+    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(cause);
+        }
+    }
+
+    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
+        log.warn(this.manager.Name() + "\tsessionIdle");
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionIdle();
+        }
+        session.close(true);
+    }
+
+    public void messageReceived(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        this.manager.AppendToRece(packet);
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\trece\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\trece\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+
+    public void messageSent(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\tsend\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\tsend\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+}

+ 216 - 0
src/main/java/com/persagy/iottransfer/communication/mina/udp/client/UDPClientManager.java

@@ -0,0 +1,216 @@
+package com.persagy.iottransfer.communication.mina.udp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.mina.codec.MinaCodecFactory;
+import com.persagy.iottransfer.communication.util.*;
+import com.persagy.iottransfer.config.IotProperties;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.future.ConnectFuture;
+import org.apache.mina.core.service.IoConnector;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.transport.socket.nio.NioDatagramConnector;
+
+import java.net.InetSocketAddress;
+
+@Slf4j
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UDPClientManager implements IClientManager {
+    String projectId;
+    IotProperties.Client client;
+    String ip;
+    int port;
+    String targetIp;
+    int targetPort;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    boolean sessionClosed = false;
+
+    IClientHandler handlerManager;
+    ILogger logger;
+
+    public final PacketBuffer<Packet> receList = new PacketBuffer<Packet>();
+
+    IoSession session;
+    IoConnector connector;
+    int remark_count = 0;
+
+    public UDPClientManager(String targetIp, int targetPort, String encoding, int Max_size) {
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+    }
+
+    public UDPClientManager(String ip, int port, String targetIp, int targetPort, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+    }
+
+    public UDPClientManager(String targetIp, int targetPort, String encoding, boolean compress, int Max_size) {
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public UDPClientManager(String ip, int port, String targetIp, int targetPort, String encoding, boolean compress,
+                            int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public UDPClientManager(String ip, int port, String targetIp, int targetPort, String encoding, String aes_password,
+                            boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public void setHandlerManager(IClientHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    @Override
+    public String getProjectId() {
+        return this.projectId;
+    }
+    @Override
+    public IotProperties.Client getClient() {
+        return this.client;
+    }
+    public String Name() {
+        if (this.ip == null) {
+            return "UDP Client " + this.targetIp + ":" + this.targetPort;
+        } else {
+            return "UDP Client " + this.ip + ":" + this.port;
+        }
+    }
+
+    public synchronized boolean IsSessionClosed() {
+        return this.sessionClosed;
+    }
+
+    public synchronized void SetSessionClosed(boolean value) {
+        this.sessionClosed = value;
+    }
+
+    public synchronized void Start() {
+        if (this.session == null) {
+            try {
+                IoConnector connectorInner = new NioDatagramConnector();
+                ProtocolCodecFactory factory;
+                if (this.ip == null) {
+                    factory = new MinaCodecFactory(this.targetIp, this.targetPort, this.encoding, this.aes_password,
+                            this.compress);
+                } else {
+                    factory = new MinaCodecFactory(this.ip, this.port, this.encoding, this.aes_password, this.compress);
+                }
+                connectorInner.getFilterChain().addLast("codec", new ProtocolCodecFilter(factory));
+                connectorInner.setHandler(new UDPClientIoHandler(this));
+                ConnectFuture connectFuture;
+                if (this.ip == null) {
+                    connectFuture = connectorInner.connect(new InetSocketAddress(this.targetIp, this.targetPort));
+                } else {
+                    connectFuture = connectorInner.connect(new InetSocketAddress(this.targetIp, this.targetPort),
+                            new InetSocketAddress(this.ip, this.port));
+                }
+
+                connectFuture.awaitUninterruptibly();
+                if (connectFuture.isDone()) {
+                    if (connectFuture.isConnected()) {
+                        this.session = connectFuture.getSession();
+                        this.connector = connectorInner;
+                    } else {
+                        connectorInner.dispose();
+                        throw new Exception();
+                    }
+                } else {
+                    connectorInner.dispose();
+                    throw new Exception();
+                }
+
+                log.warn(this.Name() + "\tStart");
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+            }
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new Packet(), Integer.MAX_VALUE);
+        }
+        if (this.session != null) {
+            // CloseFuture closeFuture = this.session.close(true);
+            // closeFuture.awaitUninterruptibly();
+            this.session.close(true);
+            this.session = null;
+
+            this.connector.dispose();
+            this.connector = null;
+        }
+    }
+
+    public void AppendToSend(Packet MyPackage) {
+        if (this.session == null) {
+            this.Start();
+        }
+        if (this.session != null) {
+            this.session.write(MyPackage);
+        }
+    }
+
+    public void AppendToRece(Packet MyPackage) {
+        this.receList.offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopRece() {
+        Packet entity = this.receList.poll();
+        return entity;
+    }
+
+    public Packet takeRece() throws InterruptedException {
+        Packet MyPackage = this.receList.take();
+        return MyPackage;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+
+}

+ 88 - 0
src/main/java/com/persagy/iottransfer/communication/mina/udp/server/UDPServerIoHandler.java

@@ -0,0 +1,88 @@
+package com.persagy.iottransfer.communication.mina.udp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.service.IoHandlerAdapter;
+import org.apache.mina.core.session.IdleStatus;
+import org.apache.mina.core.session.IoSession;
+
+import java.net.SocketAddress;
+import java.util.Date;
+
+@Slf4j
+public class UDPServerIoHandler extends IoHandlerAdapter {
+    UDPServerManager manager;
+
+    public UDPServerIoHandler(UDPServerManager manager) {
+        this.manager = manager;
+    }
+
+    public void sessionCreated(IoSession session) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        log.info(this.manager.Name() + "\tsessionCreated\t" + remoteAddress);
+    }
+
+    public void sessionOpened(IoSession session) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        this.manager.SetConnectTime(remoteAddress, new Date());
+        if (!this.manager.socketMap.containsKey(remoteAddress)) {
+            this.manager.socketMap.put(remoteAddress, session);
+        }
+        log.warn(this.manager.Name() + "\tsessionOpened\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionOpened(session.getRemoteAddress());
+        }
+    }
+
+    public void sessionClosed(IoSession session) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        this.manager.SetConnectTime(remoteAddress, null);
+        this.manager.socketMap.remove(remoteAddress);
+        log.warn(this.manager.Name() + "\tsessionClosed\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionClosed(session.getRemoteAddress());
+        }
+    }
+
+    public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(session.getRemoteAddress(), cause);
+        }
+    }
+
+    public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
+        SocketAddress socketAddress = session.getRemoteAddress();
+        String remoteAddress = socketAddress.toString();
+        log.warn(this.manager.Name() + "\tsessionIdle\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionIdle(session.getRemoteAddress());
+        }
+    }
+
+    public void messageReceived(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        this.manager.AppendToRece(session, packet);
+        SocketAddress socketAddress = session.getRemoteAddress();
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\trece\t" + socketAddress.toString() + "\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\trece\t" + socketAddress.toString()
+                    + "\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+
+    public void messageSent(IoSession session, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        SocketAddress socketAddress = session.getRemoteAddress();
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\tsend\t" + socketAddress.toString() + "\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\tsend\t" + socketAddress.toString()
+                    + "\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+}

+ 199 - 0
src/main/java/com/persagy/iottransfer/communication/mina/udp/server/UDPServerManager.java

@@ -0,0 +1,199 @@
+package com.persagy.iottransfer.communication.mina.udp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.entity.UDPSendEntity;
+import com.persagy.iottransfer.communication.mina.codec.MinaCodecFactory;
+import com.persagy.iottransfer.communication.util.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.mina.core.session.IoSession;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolCodecFilter;
+import org.apache.mina.transport.socket.DatagramSessionConfig;
+import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UDPServerManager implements IServerManager {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    IServerHandler handlerManager;
+    ILogger logger;
+
+    Map<String, Date> connectDateMap = new HashMap<String, Date>();
+    public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+
+    boolean allowJustSend = false;
+
+    NioDatagramAcceptor acceptor;
+    Map<String, IoSession> socketMap = new HashMap<String, IoSession>();
+    int remark_count = 0;
+
+    public UDPServerManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+    }
+
+    public UDPServerManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public UDPServerManager(String ip, int port, String encoding, String aes_password, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public void setHandlerManager(IServerHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    public String Name() {
+        return "UDP Server " + this.ip + ":" + this.port;
+    }
+
+    public synchronized void Start() {
+        if (this.acceptor == null) {
+            try {
+                NioDatagramAcceptor acceptorInner = new NioDatagramAcceptor();
+                ProtocolCodecFactory factory = new MinaCodecFactory(this.ip, this.port, this.encoding,
+                        this.aes_password, this.compress);
+                acceptorInner.getFilterChain().addLast("protocol", new ProtocolCodecFilter(factory));
+                acceptorInner.setHandler(new UDPServerIoHandler(this));
+
+                DatagramSessionConfig dcfg = acceptorInner.getSessionConfig();
+                dcfg.setReuseAddress(true);
+
+                acceptorInner.bind(new InetSocketAddress(this.ip, this.port));
+
+                this.acceptor = acceptorInner;
+
+                log.warn(this.Name() + "\tStart");
+            } catch (IOException e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+            }
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new PacketEntity(), Integer.MAX_VALUE);
+        }
+        if (this.acceptor != null) {
+            String[] clientAddress_array = this.GetClientAddresss();
+            for (String clientAddress : clientAddress_array) {
+                try {
+                    this.closeClient(clientAddress);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+            this.acceptor.unbind();
+            this.acceptor.dispose();
+            this.acceptor = null;
+        }
+    }
+
+    public synchronized void AllowJustSend_UDP(boolean allow) {
+        this.allowJustSend = allow;
+    }
+
+    public synchronized String[] GetClientAddresss() {
+        return this.connectDateMap.keySet().toArray(new String[0]);
+    }
+
+    public synchronized Date GetConnectTime(String clientAddress) {
+        if (this.connectDateMap.containsKey(clientAddress)) {
+            return this.connectDateMap.get(clientAddress);
+        }
+        return null;
+    }
+
+    public synchronized void SetConnectTime(String clientAddress, Date date) {
+        this.connectDateMap.remove(clientAddress);
+        if (date != null) {
+            this.connectDateMap.put(clientAddress, date);
+        }
+    }
+
+    public void AppendToSend(String clientAddress, Packet MyPackage) {
+        if (this.allowJustSend && !this.socketMap.containsKey(clientAddress)) {
+            int index = clientAddress.indexOf(':');
+            String remote_ip = clientAddress.substring(1, index);
+            int remote_port = Integer.parseInt(clientAddress.substring(index + 1));
+            // newSession�ἤ��sessionCreated��sessionOpened
+            this.acceptor.newSession(new InetSocketAddress(remote_ip, remote_port),
+                    new InetSocketAddress(this.ip, this.port));
+        }
+        IoSession session = this.socketMap.get(clientAddress);
+        if (session != null) {
+            session.write(MyPackage);
+        }
+    }
+
+    public UDPSendEntity PopSend() {
+        return null;
+    }
+
+    public void AppendToRece(IoSession sa, Packet MyPackage) {
+        String clientAddress = sa.getRemoteAddress().toString();
+        if (!this.socketMap.containsKey(clientAddress)) {
+            this.socketMap.put(clientAddress, sa);
+        }
+        PacketEntity entity = new PacketEntity();
+        entity.address = clientAddress;
+        entity.content = MyPackage;
+        this.receList.offer(entity, this.Max_size);
+    }
+
+    public PacketEntity PopRece() {
+        PacketEntity entity = this.receList.poll();
+        return entity;
+    }
+
+    public PacketEntity takeRece() throws InterruptedException {
+        PacketEntity entity = this.receList.take();
+        return entity;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void closeClient(String clientAddress) {
+        this.socketMap.remove(clientAddress);
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 92 - 0
src/main/java/com/persagy/iottransfer/communication/netty/codec/NettyPacketDecoder.java

@@ -0,0 +1,92 @@
+package com.persagy.iottransfer.communication.netty.codec;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.MyDecoder;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class NettyPacketDecoder extends ByteToMessageDecoder {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+
+    boolean separate = false;
+    boolean separateBytes = false;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    MyDecoder decoder;
+    Map<String, List<Byte>> tmpByteListMap = new HashMap<String, List<Byte>>();
+
+    public NettyPacketDecoder(String ip, int port, String encoding, String aes_password, boolean compress) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.compress = compress;
+
+        this.separate = false;
+
+        this.decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public NettyPacketDecoder(String ip, int port, String encoding, String aes_password, boolean compress, byte prefix,
+                              byte suffix) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public NettyPacketDecoder(String ip, int port, String encoding, String aes_password, boolean compress,
+                              byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+
+        this.aes_password = aes_password;
+        this.encoding = encoding;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    @Override
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        int count = in.readableBytes();
+        byte[] bytes = new byte[count];
+        in.readBytes(bytes);
+
+        String remoteAddress = ctx.channel().remoteAddress().toString();
+        List<Packet> packetList = this.decoder.decode(remoteAddress, bytes);
+        for (int i = 0; i < packetList.size(); i++) {
+            Packet packet = packetList.get(i);
+            out.add(packet);
+        }
+    }
+
+}

+ 79 - 0
src/main/java/com/persagy/iottransfer/communication/netty/codec/NettyPacketEncoder.java

@@ -0,0 +1,79 @@
+package com.persagy.iottransfer.communication.netty.codec;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.MyEncoder;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.MessageToByteEncoder;
+
+public class NettyPacketEncoder extends MessageToByteEncoder<Packet> {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+
+    boolean separate = false;
+    boolean separateBytes = false;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    MyEncoder encoder;
+
+    public NettyPacketEncoder(String ip, int port, String encoding, String aes_password, boolean compress) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.compress = compress;
+
+        this.separate = false;
+
+        this.encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public NettyPacketEncoder(String ip, int port, String encoding, String aes_password, boolean compress, byte prefix,
+                              byte suffix) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    public NettyPacketEncoder(String ip, int port, String encoding, String aes_password, boolean compress,
+                              byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, this.separate,
+                this.separateBytes, this.prefix, this.suffix, this.prefixBytes, this.suffixBytes);
+    }
+
+    @Override
+    protected void encode(ChannelHandlerContext ctx, Packet message, ByteBuf out) throws Exception {
+        Packet request = message;
+        byte[] comm_bytes = this.encoder.encode(request);
+        out.writeBytes(comm_bytes);
+    }
+}

+ 58 - 0
src/main/java/com/persagy/iottransfer/communication/netty/tcp/client/ClientChannelInitializer.java

@@ -0,0 +1,58 @@
+package com.persagy.iottransfer.communication.netty.tcp.client;
+
+import com.persagy.iottransfer.communication.netty.codec.NettyPacketDecoder;
+import com.persagy.iottransfer.communication.netty.codec.NettyPacketEncoder;
+import com.persagy.iottransfer.communication.util.MySslContextFactory;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.timeout.IdleStateHandler;
+
+import javax.net.ssl.SSLEngine;
+
+public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
+    NettyTCPClientManager manager;
+
+    public ClientChannelInitializer(NettyTCPClientManager manager) {
+        this.manager = manager;
+    }
+
+    @Override
+    protected void initChannel(SocketChannel ch) throws Exception {
+        NettyPacketEncoder encoder;
+        NettyPacketDecoder decoder;
+        NettyTCPClientHandler handler = new NettyTCPClientHandler(manager);
+        if (manager.separate) {
+            if (manager.separateBytes) {
+                encoder = new NettyPacketEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefixBytes, manager.suffixBytes);
+                decoder = new NettyPacketDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefixBytes, manager.suffixBytes);
+            } else {
+                encoder = new NettyPacketEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefix, manager.suffix);
+                decoder = new NettyPacketDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefix, manager.suffix);
+            }
+        } else {
+            encoder = new NettyPacketEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                    manager.compress);
+            decoder = new NettyPacketDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                    manager.compress);
+        }
+
+        if (manager.ssl_file_km != null || manager.ssl_file_tm != null) {
+            SSLEngine engine = MySslContextFactory
+                    .getContext(manager.ssl_protocol, manager.ssl_keystoretype, manager.ssl_algorithm,
+                            manager.ssl_file_km, manager.ssl_file_tm, manager.ssl_password_km, manager.ssl_password_tm)
+                    .createSSLEngine();
+            engine.setUseClientMode(true);
+            ch.pipeline().addFirst("ssl", new SslHandler(engine));
+        }
+        if (manager.IdleTime != null) {
+            ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(0, 0, manager.IdleTime));
+        }
+        ch.pipeline().addLast(encoder, decoder, handler);
+    }
+
+}

+ 66 - 0
src/main/java/com/persagy/iottransfer/communication/netty/tcp/client/NettyTCPClientHandler.java

@@ -0,0 +1,66 @@
+package com.persagy.iottransfer.communication.netty.tcp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.handler.timeout.IdleStateEvent;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class NettyTCPClientHandler extends ChannelInboundHandlerAdapter {
+    NettyTCPClientManager manager;
+
+    public NettyTCPClientHandler(NettyTCPClientManager manager) {
+        this.manager = manager;
+    }
+
+    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelRegistered(ctx);
+
+        this.manager.SetSessionClosed(false);
+        log.warn(this.manager.Name() + "\tsessionOpened");
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionOpened();
+        }
+    }
+
+    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelUnregistered(ctx);
+
+        log.warn(this.manager.Name() + "\tsessionClosed");
+        // �쳣�ر�
+        this.manager.Stop();
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionClosed();
+        }
+    }
+
+    public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        this.manager.AppendToRece(packet);
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\trece\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\trece\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(cause);
+        }
+    }
+
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+        super.userEventTriggered(ctx, evt);
+
+        if (evt instanceof IdleStateEvent) {
+            log.warn(this.manager.Name() + "\tsessionIdle");
+            if (this.manager.handlerManager != null) {
+                this.manager.handlerManager.sessionIdle();
+            }
+        }
+    }
+
+}

+ 387 - 0
src/main/java/com/persagy/iottransfer/communication/netty/tcp/client/NettyTCPClientManager.java

@@ -0,0 +1,387 @@
+package com.persagy.iottransfer.communication.netty.tcp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.*;
+import com.persagy.iottransfer.config.IotProperties;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.InetSocketAddress;
+
+@Slf4j
+public class NettyTCPClientManager implements IClientManager {
+    private final EventLoopGroup workerGroup = new NioEventLoopGroup(1);
+    String projectId;
+    IotProperties.Client client;
+    String ip;
+    int port;
+    String encoding;
+    String ssl_protocol;
+    String ssl_keystoretype;
+    String ssl_algorithm;
+    byte[] ssl_file_km;
+    String ssl_password_km;
+    byte[] ssl_file_tm;
+    String ssl_password_tm;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+    boolean separate;
+    boolean separateBytes;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+    Integer IdleTime = null;
+    boolean sessionClosed = false;
+    IClientHandler handlerManager;
+    ILogger logger;
+    public final PacketBuffer<Packet> receList = new PacketBuffer<Packet>();
+    boolean started = false;
+    String localAddress = "()";
+    int remark_count = 0;
+    private ChannelFuture future;
+    private Bootstrap bootstrap;
+
+    public NettyTCPClientManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, int Max_size, byte[] prefixBytes,
+                                 byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size, byte prefix,
+                                 byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size,
+                                 byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, boolean compress, Integer IdleTime,
+                                 int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                                 byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                                 byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                                 Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                                 Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                                 Integer IdleTime, int Max_size, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                                 String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                                 String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                                 String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                                 String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPClientManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                                 String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                                 String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte[] prefixBytes,
+                                 byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public void setHandlerManager(IClientHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    public String Name() {
+        return "TCP Client " + this.ip + ":" + this.port + localAddress;
+    }
+
+    public synchronized boolean IsSessionClosed() {
+        return this.sessionClosed;
+    }
+
+    public synchronized void SetSessionClosed(boolean value) {
+        this.sessionClosed = value;
+    }
+
+    public synchronized void Start() {
+        if (started) {
+            return;
+        }
+
+        try {
+            bootstrap = new Bootstrap();
+            bootstrap.group(workerGroup).channel(NioSocketChannel.class).handler(new ClientChannelInitializer(this));
+            future = bootstrap.connect(new InetSocketAddress(this.ip, this.port));
+
+            started = true;
+            log.warn(this.Name() + "\tStart");
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+            try {
+                workerGroup.shutdownGracefully();
+            } catch (Exception e1) {
+                e1.printStackTrace();
+            }
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new Packet(), Integer.MAX_VALUE);
+        }
+        if (!this.started) {
+            return;
+        }
+
+        try {
+            workerGroup.shutdownGracefully();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void AppendToSend(Packet MyPackage) {
+        if (!this.started) {
+            this.Start();
+        }
+        if (this.started) {
+            future.channel().writeAndFlush(MyPackage);
+
+            Packet packet = MyPackage;
+            if (this.encoding != null) {
+                log.info(this.Name() + "\tsend\t" + packet.packetString);
+            } else {
+                log.info(this.Name() + "\tsend\t" + HexToByte.byteToHex(packet.packetBytes));
+            }
+        }
+    }
+
+    public void AppendToRece(Packet MyPackage) {
+        this.receList.offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopRece() {
+        Packet MyPackage = this.receList.poll();
+        return MyPackage;
+    }
+
+    public Packet takeRece() throws InterruptedException {
+        Packet MyPackage = this.receList.take();
+        return MyPackage;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+    @Override
+    public String getProjectId() {
+        return this.projectId;
+    }
+    @Override
+    public IotProperties.Client getClient() {
+        return this.client;
+    }
+}

+ 90 - 0
src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/NettyTCPServerHandler.java

@@ -0,0 +1,90 @@
+package com.persagy.iottransfer.communication.netty.tcp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.timeout.IdleStateEvent;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.SocketAddress;
+import java.util.Date;
+
+@Slf4j
+@SuppressWarnings("unchecked")
+public class NettyTCPServerHandler extends ChannelInboundHandlerAdapter {
+    NettyTCPServerManager manager;
+
+    public NettyTCPServerHandler(NettyTCPServerManager manager) {
+        this.manager = manager;
+    }
+
+    public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
+        Packet packet = (Packet) message;
+        SocketAddress socketAddress = ctx.channel().remoteAddress();
+        this.manager.AppendToRece(socketAddress.toString(), packet);
+        if (this.manager.encoding != null) {
+            log.info(this.manager.Name() + "\trece\t" + socketAddress + "\t" + packet.packetString);
+        } else {
+            log.info(this.manager.Name() + "\trece\t" + socketAddress
+                    + "\t" + HexToByte.byteToHex(packet.packetBytes));
+        }
+    }
+
+    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelRegistered(ctx);
+
+        SocketAddress socketAddress = ctx.channel().remoteAddress();
+        String remoteAddress = socketAddress.toString();
+        this.manager.SetConnectTime(remoteAddress, new Date());
+        if (!this.manager.socketMap.containsKey(remoteAddress)) {
+            this.manager.socketMap.put(remoteAddress, ctx.channel());
+        }
+        log.warn(this.manager.Name() + "\t" + "sessionOpened\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionOpened(ctx.channel().remoteAddress());
+        }
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        super.channelActive(ctx);
+
+        SocketAddress socketAddress = ctx.channel().remoteAddress();
+        String remoteAddress = socketAddress.toString();
+        log.warn(this.manager.Name() + "\t" + "channelActive\t" + remoteAddress);
+
+        ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener(new SSLHandshakeListener(this.manager, ctx));
+    }
+
+    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelUnregistered(ctx);
+
+        SocketAddress socketAddress = ctx.channel().remoteAddress();
+        String remoteAddress = socketAddress.toString();
+        this.manager.SetConnectTime(remoteAddress, null);
+        this.manager.socketMap.remove(remoteAddress);
+        log.warn(this.manager.Name() + "\tsessionClosed\t" + remoteAddress);
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionClosed(ctx.channel().remoteAddress());
+        }
+    }
+
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(ctx.channel().remoteAddress(), cause);
+        }
+    }
+
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+        super.userEventTriggered(ctx, evt);
+
+        if (evt instanceof IdleStateEvent) {
+            SocketAddress socketAddress = ctx.channel().remoteAddress();
+            String remoteAddress = socketAddress.toString();
+            log.warn(this.manager.Name() + "\tsessionIdle\t" + remoteAddress);
+            ctx.channel().close();
+        }
+    }
+}

+ 411 - 0
src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/NettyTCPServerManager.java

@@ -0,0 +1,411 @@
+package com.persagy.iottransfer.communication.netty.tcp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.util.*;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+public class NettyTCPServerManager implements IServerManager {
+    String ip;
+    int port;
+    String encoding;
+    String ssl_protocol;
+    String ssl_keystoretype;
+    String ssl_algorithm;
+    byte[] ssl_file_km;
+    String ssl_password_km;
+    byte[] ssl_file_tm;
+    String ssl_password_tm;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    boolean separate;
+    boolean separateBytes;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    Integer IdleTime = null;
+
+    IServerHandler handlerManager;
+    ILogger logger;
+
+    Map<String, Date> connectDateMap = new HashMap<String, Date>();
+    public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
+    EventLoopGroup workerGroup = new NioEventLoopGroup();
+    Map<String, Channel> socketMap = new HashMap<String, Channel>();
+    int remark_count = 0;
+    private boolean init = false;
+    private ServerBootstrap bootstrap;
+
+    public NettyTCPServerManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, int Max_size, byte[] prefixBytes,
+                                 byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size, byte prefix,
+                                 byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size,
+                                 byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, boolean compress, Integer IdleTime,
+                                 int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                                 byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, boolean compress, Integer IdleTime, int Max_size,
+                                 byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                                 Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                                 Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                                 Integer IdleTime, int Max_size, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                                 String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                                 String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                                 String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                                 String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public NettyTCPServerManager(String ip, int port, String encoding, String ssl_protocol, String ssl_keystoretype,
+                                 String ssl_algorithm, byte[] ssl_file_km, String ssl_password_km, byte[] ssl_file_tm,
+                                 String ssl_password_tm, boolean compress, Integer IdleTime, int Max_size, byte[] prefixBytes,
+                                 byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.ssl_protocol = ssl_protocol;
+        this.ssl_keystoretype = ssl_keystoretype;
+        this.ssl_algorithm = ssl_algorithm;
+        this.ssl_file_km = ssl_file_km;
+        this.ssl_password_km = ssl_password_km;
+        this.ssl_file_tm = ssl_file_tm;
+        this.ssl_password_tm = ssl_password_tm;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.IdleTime = IdleTime;
+    }
+
+    public void setHandlerManager(IServerHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    public String Name() {
+        return "TCP Server " + this.ip + ":" + this.port;
+    }
+
+    public synchronized void Start() {
+        if (this.init) {
+            return;
+        }
+
+        try {
+            bootstrap = new ServerBootstrap();
+            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
+                    .childHandler(new ServerChannelInitializer(this)).childOption(ChannelOption.TCP_NODELAY, true);
+            bootstrap.bind(this.ip, this.port).sync();
+            init = true;
+            log.warn(this.Name() + "\tStart");
+        } catch (Exception e) {
+            log.error(e.getMessage(), e);
+            try {
+                workerGroup.shutdownGracefully();
+            } catch (Exception e1) {
+                e1.printStackTrace();
+            }
+        }
+    }
+
+    public void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new PacketEntity(), Integer.MAX_VALUE);
+        }
+        if (!this.init) {
+            return;
+        }
+        try {
+            workerGroup.shutdownGracefully();
+            bossGroup.shutdownGracefully();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public synchronized void AllowJustSend_UDP(boolean allow) {
+
+    }
+
+    public synchronized String[] GetClientAddresss() {
+        return this.connectDateMap.keySet().toArray(new String[0]);
+    }
+
+    public synchronized Date GetConnectTime(String clientAddress) {
+        if (this.connectDateMap.containsKey(clientAddress)) {
+            return this.connectDateMap.get(clientAddress);
+        }
+        return null;
+    }
+
+    public synchronized void SetConnectTime(String clientAddress, Date date) {
+        this.connectDateMap.remove(clientAddress);
+        if (date != null) {
+            this.connectDateMap.put(clientAddress, date);
+        }
+    }
+
+    public void AppendToSend(String clientAddress, Packet MyPackage) {
+        Channel session = this.socketMap.get(clientAddress);
+        if (session != null) {
+            session.writeAndFlush(MyPackage);
+
+            Packet packet = MyPackage;
+            if (this.encoding != null) {
+                log.info(this.Name() + "\tsend\t" + packet.packetString);
+            } else {
+                log.info(this.Name() + "\tsend\t" + HexToByte.byteToHex(packet.packetBytes));
+            }
+        }
+    }
+
+    public synchronized boolean ContainsSocket(String clientAddress) {
+        return this.socketMap.containsKey(clientAddress);
+    }
+
+    public void AppendToRece(String clientAddress, Packet MyPackage) {
+        PacketEntity entity = new PacketEntity();
+        entity.address = clientAddress;
+        entity.content = MyPackage;
+        this.receList.offer(entity, this.Max_size);
+    }
+
+    public PacketEntity PopRece() {
+        PacketEntity entity = this.receList.poll();
+        return entity;
+    }
+
+    public PacketEntity takeRece() throws InterruptedException {
+        PacketEntity entity = this.receList.take();
+        return entity;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void closeClient(String clientAddress) {
+        if (this.socketMap.containsKey(clientAddress)) {
+            Channel session = this.socketMap.get(clientAddress);
+            session.close();
+            this.socketMap.remove(clientAddress);
+        }
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 49 - 0
src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/SSLHandshakeListener.java

@@ -0,0 +1,49 @@
+package com.persagy.iottransfer.communication.netty.tcp.server;
+
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
+import lombok.extern.slf4j.Slf4j;
+
+import javax.net.ssl.SSLSession;
+import javax.security.cert.X509Certificate;
+import java.net.SocketAddress;
+import java.text.SimpleDateFormat;
+
+@Slf4j
+@SuppressWarnings("rawtypes")
+public class SSLHandshakeListener implements GenericFutureListener {
+    NettyTCPServerManager manager;
+    ChannelHandlerContext ctx;
+
+    public SSLHandshakeListener(NettyTCPServerManager manager, ChannelHandlerContext ctx) {
+        this.manager = manager;
+        this.ctx = ctx;
+    }
+
+    @Override
+    public void operationComplete(Future future) throws Exception {
+        SocketAddress socketAddress = ctx.channel().remoteAddress();
+        String remoteAddress = socketAddress.toString();
+        if (future.isSuccess()) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
+
+            SSLSession ss = ctx.pipeline().get(SslHandler.class).engine().getSession();
+            StringBuffer sb = new StringBuffer();
+            sb.append("\n" + "cipherSuite:" + ss.getCipherSuite());
+            X509Certificate cert = ss.getPeerCertificateChain()[0];
+            sb.append("\n" + "version:" + cert.getVersion());
+            sb.append("\n" + "serialNumber:" + cert.getSerialNumber().toString(16));
+            sb.append("\n" + "from:" + sdf.format(cert.getNotBefore()));
+            sb.append("\n" + "to:" + sdf.format(cert.getNotAfter()));
+            sb.append("\n" + "subjectDN:" + cert.getSubjectDN().getName());
+            sb.append("\n" + "issuerDN:" + cert.getIssuerDN().getName());
+            sb.append("\n" + "sigAlg:" + cert.getSigAlgName());
+
+            log.warn(this.manager.Name() + "\t" + "handshake success" + "\t" + remoteAddress + sb);
+        } else {
+            log.warn(this.manager.Name() + "\t" + "handshake failure" + "\t" + remoteAddress);
+        }
+    }
+}

+ 61 - 0
src/main/java/com/persagy/iottransfer/communication/netty/tcp/server/ServerChannelInitializer.java

@@ -0,0 +1,61 @@
+package com.persagy.iottransfer.communication.netty.tcp.server;
+
+import com.persagy.iottransfer.communication.netty.codec.NettyPacketDecoder;
+import com.persagy.iottransfer.communication.netty.codec.NettyPacketEncoder;
+import com.persagy.iottransfer.communication.util.MySslContextFactory;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.handler.timeout.IdleStateHandler;
+
+import javax.net.ssl.SSLEngine;
+
+public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
+    NettyTCPServerManager manager;
+
+    public ServerChannelInitializer(NettyTCPServerManager manager) {
+        this.manager = manager;
+    }
+
+    @Override
+    protected void initChannel(SocketChannel ch) throws Exception {
+        NettyPacketEncoder encoder;
+        NettyPacketDecoder decoder;
+        NettyTCPServerHandler handler = new NettyTCPServerHandler(manager);
+        if (manager.separate) {
+            if (manager.separateBytes) {
+                encoder = new NettyPacketEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefixBytes, manager.suffixBytes);
+                decoder = new NettyPacketDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefixBytes, manager.suffixBytes);
+            } else {
+                encoder = new NettyPacketEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefix, manager.suffix);
+                decoder = new NettyPacketDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                        manager.compress, manager.prefix, manager.suffix);
+            }
+        } else {
+            encoder = new NettyPacketEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                    manager.compress);
+            decoder = new NettyPacketDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password,
+                    manager.compress);
+        }
+
+        if (manager.ssl_file_km != null || manager.ssl_file_tm != null) {
+            SSLEngine engine = MySslContextFactory
+                    .getContext(manager.ssl_protocol, manager.ssl_keystoretype, manager.ssl_algorithm,
+                            manager.ssl_file_km, manager.ssl_file_tm, manager.ssl_password_km, manager.ssl_password_tm)
+                    .createSSLEngine();
+            engine.setUseClientMode(false);
+            if (manager.ssl_file_tm != null) {
+                engine.setNeedClientAuth(true);
+            }
+            ch.pipeline().addFirst("ssl", new SslHandler(engine));
+        }
+        if (manager.IdleTime != null) {
+            ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(0, 0, manager.IdleTime));
+        }
+        ch.pipeline().addLast(encoder, decoder, handler);
+    }
+
+}

+ 76 - 0
src/main/java/com/persagy/iottransfer/communication/netty/udp/client/NettyUDPClientHandler.java

@@ -0,0 +1,76 @@
+package com.persagy.iottransfer.communication.netty.udp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.handler.timeout.IdleStateEvent;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+@Slf4j
+public class NettyUDPClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
+    NettyUDPClientManager manager;
+
+    public NettyUDPClientHandler(NettyUDPClientManager manager) {
+        this.manager = manager;
+    }
+
+    public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
+        int count = msg.content().readableBytes();
+        byte[] bytes = new byte[count];
+        msg.content().readBytes(bytes);
+        String remoteAddress = msg.sender().toString();
+        List<Packet> packetList = this.manager.decoder.decode(remoteAddress, bytes);
+        for (int i = 0; i < packetList.size(); i++) {
+            Packet packet = packetList.get(i);
+            this.manager.receList.offer(packet, this.manager.Max_size);
+
+            if (this.manager.encoding != null) {
+                log.info(this.manager.Name() + "\trece\t" + remoteAddress + "\t" + packet.packetString);
+            } else {
+                log.info(this.manager.Name() + "\trece\t" + remoteAddress + "\t"
+                        + HexToByte.byteToHex(packet.packetBytes));
+            }
+        }
+    }
+
+    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelRegistered(ctx);
+
+        log.warn(this.manager.Name() + "\tsessionOpened");
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionOpened();
+        }
+    }
+
+    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelUnregistered(ctx);
+
+        log.warn(this.manager.Name() + "\tsessionClosed");
+        // �쳣�ر�
+        this.manager.Stop();
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.sessionClosed();
+        }
+    }
+
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(cause);
+        }
+    }
+
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+        super.userEventTriggered(ctx, evt);
+
+        if (evt instanceof IdleStateEvent) {
+            log.warn(this.manager.Name() + "\tsessionIdle");
+            if (this.manager.handlerManager != null) {
+                this.manager.handlerManager.sessionIdle();
+            }
+        }
+    }
+}

+ 226 - 0
src/main/java/com/persagy/iottransfer/communication/netty/udp/client/NettyUDPClientManager.java

@@ -0,0 +1,226 @@
+package com.persagy.iottransfer.communication.netty.udp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.UDPSendEntity;
+import com.persagy.iottransfer.communication.util.*;
+import com.persagy.iottransfer.config.IotProperties;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.*;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.DatagramSocket;
+import java.net.InetSocketAddress;
+
+@Slf4j
+public class NettyUDPClientManager implements IClientManager {
+    String projectId;
+    IotProperties.Client client;
+    String ip;
+    int port;
+    String targetIp;
+    int targetPort;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    boolean sessionClosed = false;
+
+    IClientHandler handlerManager;
+    ILogger logger;
+
+    public final PacketBuffer<Packet> receList = new PacketBuffer<Packet>();
+
+    boolean started = false;
+    EventLoopGroup group = new NioEventLoopGroup(1);
+    Channel channel;
+    InetSocketAddress remoteAddress;
+    MyEncoder encoder;
+    MyDecoder decoder;
+    int remark_count = 0;
+
+    public NettyUDPClientManager(String targetIp, int targetPort, String encoding, int Max_size) {
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+    }
+
+    public NettyUDPClientManager(String ip, int port, String targetIp, int targetPort, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+    }
+
+    public NettyUDPClientManager(String targetIp, int targetPort, String encoding, boolean compress, int Max_size) {
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public NettyUDPClientManager(String ip, int port, String targetIp, int targetPort, String encoding,
+                                 boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public NettyUDPClientManager(String ip, int port, String targetIp, int targetPort, String encoding,
+                                 String aes_password, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public void setHandlerManager(IClientHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    @Override
+    public String getProjectId() {
+        return this.projectId;
+    }
+    @Override
+    public IotProperties.Client getClient() {
+        return this.client;
+    }
+    public String Name() {
+        if (this.ip == null) {
+            return "UDP Client " + this.targetIp + ":" + this.targetPort;
+        } else {
+            return "UDP Client " + this.ip + ":" + this.port;
+        }
+    }
+
+    public synchronized boolean IsSessionClosed() {
+        return this.sessionClosed;
+    }
+
+    public synchronized void SetSessionClosed(boolean value) {
+        this.sessionClosed = value;
+    }
+
+    public synchronized void Start() {
+        if (this.started) {
+            return;
+        }
+
+        try {
+            if (this.ip == null) {
+                this.ip = "0.0.0.0";
+                int tmp_port = 2046;
+                DatagramSocket DatagramSocket;
+                while (true) {
+                    try {
+                        DatagramSocket = new DatagramSocket(null);
+                        DatagramSocket.bind(new InetSocketAddress(this.ip, tmp_port));
+                        break;
+                    } catch (Exception e) {
+                        tmp_port++;
+                    }
+                }
+                DatagramSocket.close();
+                this.port = tmp_port;
+            }
+            remoteAddress = new InetSocketAddress(this.targetIp, this.targetPort);
+            encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, false, false,
+                    (byte) '(', (byte) ')', null, null);
+            decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, false, false,
+                    (byte) '(', (byte) ')', null, null);
+            final NettyUDPClientHandler handler = new NettyUDPClientHandler(this);
+            Bootstrap b = new Bootstrap();
+            b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST, true)
+                    .handler(new ChannelInitializer<NioDatagramChannel>() {
+                        @Override
+                        protected void initChannel(NioDatagramChannel ch) throws Exception {
+                            ch.pipeline().addLast(handler);
+                        }
+                    });
+
+            ChannelFuture cf = b.bind(this.ip, this.port).sync();
+            channel = cf.channel();
+
+            this.started = true;
+            log.warn(this.Name() + "\tStart");
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        }
+    }
+
+    public void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new Packet(), Integer.MAX_VALUE);
+        }
+        if (!this.started) {
+            return;
+        }
+
+        try {
+            group.shutdownGracefully();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void AppendToSend(Packet packet) {
+        try {
+            byte[] encoded = this.encoder.encode(packet);
+            channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(encoded), remoteAddress));
+
+            if (this.encoding != null) {
+                log.info(this.Name() + "\tsend\t" + packet.packetString);
+            } else {
+                log.info(this.Name() + "\tsend\t" + HexToByte.byteToHex(packet.packetBytes));
+            }
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        }
+    }
+
+    public UDPSendEntity PopSend() {
+        return null;
+    }
+
+    public Packet PopRece() {
+        Packet entity = this.receList.poll();
+        return entity;
+    }
+
+    public Packet takeRece() throws InterruptedException {
+        Packet MyPackage = this.receList.take();
+        return MyPackage;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void closeClient(String clientAddress) {
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 73 - 0
src/main/java/com/persagy/iottransfer/communication/netty/udp/server/NettyUDPServerHandler.java

@@ -0,0 +1,73 @@
+package com.persagy.iottransfer.communication.netty.udp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.handler.timeout.IdleStateEvent;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.SocketAddress;
+import java.util.List;
+
+@Slf4j
+public class NettyUDPServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {
+    NettyUDPServerManager manager;
+
+    public NettyUDPServerHandler(NettyUDPServerManager manager) {
+        this.manager = manager;
+    }
+
+    public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
+        int count = msg.content().readableBytes();
+        byte[] bytes = new byte[count];
+        msg.content().readBytes(bytes);
+        String remoteAddress = msg.sender().toString();
+        List<Packet> packetList = this.manager.decoder.decode(remoteAddress, bytes);
+        for (int i = 0; i < packetList.size(); i++) {
+            Packet packet = packetList.get(i);
+            PacketEntity pe = new PacketEntity();
+            pe.address = msg.sender().toString();
+            pe.content = packet;
+            this.manager.receList.offer(pe, this.manager.Max_size);
+
+            if (this.manager.encoding != null) {
+                log.info(this.manager.Name() + "\trece\t" + remoteAddress + "\t" + packet.packetString);
+            } else {
+                log.info(this.manager.Name() + "\trece\t" + remoteAddress + "\t"
+                        + HexToByte.byteToHex(packet.packetBytes));
+            }
+        }
+    }
+
+    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelRegistered(ctx);
+
+        log.warn(this.manager.Name() + "\tsessionOpened\t");
+    }
+
+    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
+        super.channelUnregistered(ctx);
+
+        log.warn(this.manager.Name() + "\tsessionClosed\t");
+    }
+
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        if (this.manager.handlerManager != null) {
+            this.manager.handlerManager.exceptionCaught(ctx.channel().remoteAddress(), cause);
+        }
+    }
+
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+        super.userEventTriggered(ctx, evt);
+
+        if (evt instanceof IdleStateEvent) {
+            SocketAddress socketAddress = ctx.channel().remoteAddress();
+            String remoteAddress = socketAddress.toString();
+            log.warn(this.manager.Name() + "\tsessionIdle\t" + remoteAddress);
+            ctx.channel().close();
+        }
+    }
+}

+ 193 - 0
src/main/java/com/persagy/iottransfer/communication/netty/udp/server/NettyUDPServerManager.java

@@ -0,0 +1,193 @@
+package com.persagy.iottransfer.communication.netty.udp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.entity.UDPSendEntity;
+import com.persagy.iottransfer.communication.util.*;
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramPacket;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.InetSocketAddress;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+@Slf4j
+public class NettyUDPServerManager implements IServerManager {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    IServerHandler handlerManager;
+    ILogger logger;
+
+    Map<String, Date> connectDateMap = new HashMap<String, Date>();
+    public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+
+    boolean allowJustSend = false;
+
+    boolean started = false;
+    EventLoopGroup group = new NioEventLoopGroup(1);
+    Channel channel;
+    MyEncoder encoder;
+    MyDecoder decoder;
+    int remark_count = 0;
+
+    public NettyUDPServerManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+    }
+
+    public NettyUDPServerManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public NettyUDPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                                 int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+    }
+
+    public void setHandlerManager(IServerHandler handlerManager) {
+        this.handlerManager = handlerManager;
+    }
+
+    public void setLogger(ILogger logger) {
+        this.logger = logger;
+    }
+
+    public String Name() {
+        return "UDP Server " + this.ip + ":" + this.port;
+    }
+
+    public synchronized void Start() {
+        if (this.started) {
+            return;
+        }
+
+        try {
+            encoder = new MyEncoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, false, false,
+                    (byte) '(', (byte) ')', null, null);
+            decoder = new MyDecoder(this.ip, this.port, this.encoding, this.aes_password, this.compress, false, false,
+                    (byte) '(', (byte) ')', null, null);
+            final NettyUDPServerHandler handler = new NettyUDPServerHandler(this);
+            Bootstrap b = new Bootstrap();
+            b.group(group).channel(NioDatagramChannel.class).option(ChannelOption.SO_BROADCAST, true)
+                    .handler(new ChannelInitializer<NioDatagramChannel>() {
+                        @Override
+                        protected void initChannel(NioDatagramChannel ch) throws Exception {
+                            ch.pipeline().addLast(handler);
+                        }
+                    });
+
+            channel = b.bind(this.ip, this.port).channel();
+
+            this.started = true;
+            log.warn(this.Name() + "\tStart");
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        }
+    }
+
+    public void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new PacketEntity(), Integer.MAX_VALUE);
+        }
+        if (!this.started) {
+            return;
+        }
+
+        try {
+            group.shutdownGracefully();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public synchronized void AllowJustSend_UDP(boolean allow) {
+        this.allowJustSend = allow;
+    }
+
+    public synchronized String[] GetClientAddresss() {
+        return this.connectDateMap.keySet().toArray(new String[0]);
+    }
+
+    public synchronized Date GetConnectTime(String clientAddress) {
+        if (this.connectDateMap.containsKey(clientAddress)) {
+            return this.connectDateMap.get(clientAddress);
+        }
+        return null;
+    }
+
+    public synchronized void SetConnectTime(String clientAddress, Date date) {
+        this.connectDateMap.remove(clientAddress);
+        if (date != null) {
+            this.connectDateMap.put(clientAddress, date);
+        }
+    }
+
+    public void AppendToSend(String clientAddress, Packet packet) {
+        try {
+            byte[] encoded = this.encoder.encode(packet);
+            int index_ = clientAddress.indexOf(':');
+            String ip = clientAddress.substring(1, index_);
+            int port = Integer.parseInt(clientAddress.substring(index_ + 1));
+            InetSocketAddress remoteAddress = new InetSocketAddress(ip, port);
+            channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(encoded), remoteAddress));
+
+            if (this.encoding != null) {
+                log.info(this.Name() + "\tsend\t" + clientAddress + "\t" + packet.packetString);
+            } else {
+                log.info(this.Name() + "\tsend\t" + clientAddress + "\t" + HexToByte.byteToHex(packet.packetBytes));
+            }
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        }
+    }
+
+    public UDPSendEntity PopSend() {
+        return null;
+    }
+
+    public PacketEntity PopRece() {
+        PacketEntity entity = this.receList.poll();
+        return entity;
+    }
+
+    public PacketEntity takeRece() throws InterruptedException {
+        PacketEntity entity = this.receList.take();
+        return entity;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void closeClient(String clientAddress) {
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 201 - 0
src/main/java/com/persagy/iottransfer/communication/nio/tcp/client/NIOTCPClientManager.java

@@ -0,0 +1,201 @@
+package com.persagy.iottransfer.communication.nio.tcp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.IClientHandler;
+import com.persagy.iottransfer.communication.util.IClientManager;
+import com.persagy.iottransfer.communication.util.ILogger;
+import com.persagy.iottransfer.communication.util.PacketBuffer;
+import com.persagy.iottransfer.config.IotProperties;
+import lombok.Data;
+
+@Data
+public class NIOTCPClientManager implements IClientManager {
+    int buffer_size = 1024 * 16;
+    long SelectTimeout = 1L;
+    int SleepCount = 1000;
+    IotProperties.Client client;
+    String projectId;
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    boolean separate;
+    boolean separateBytes;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    boolean sessionClosed = false;
+
+    public final PacketBuffer<Packet> sendList = new PacketBuffer<Packet>();
+    public final PacketBuffer<Packet> receList = new PacketBuffer<Packet>();
+
+    NIOTCPClientThread thread;
+
+    ILogger logger;
+    int remark_count = 0;
+
+    public NIOTCPClientManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NIOTCPClientManager(String ip, int port, String encoding, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NIOTCPClientManager(String ip, int port, String encoding, int Max_size, byte[] prefixBytes,
+                               byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NIOTCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NIOTCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size, byte prefix,
+                               byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NIOTCPClientManager(String ip, int port, String encoding, boolean compress, int Max_size, byte[] prefixBytes,
+                               byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NIOTCPClientManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                               int Max_size, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public void setHandlerManager(IClientHandler handlerManager) {
+    }
+
+    @Override
+    public IotProperties.Client getClient() {
+        return this.client;
+    }
+
+    @Override
+    public String getProjectId() {
+        return this.projectId;
+    }
+
+    public String Name() {
+        return "TCP Client " + this.ip + ":" + this.port + " NIO";
+    }
+
+    public synchronized boolean IsSessionClosed() {
+        return this.sessionClosed;
+    }
+
+    public synchronized void SetSessionClosed(boolean value) {
+        this.sessionClosed = value;
+    }
+
+    public synchronized void Start() {
+        if (this.thread == null) {
+            this.thread = new NIOTCPClientThread(this);
+            this.thread.start();
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new Packet(), Integer.MAX_VALUE);
+        }
+        if (this.thread != null) {
+            this.thread.requestStop();
+            this.thread = null;
+        }
+    }
+
+    public void AppendToSend(Packet MyPackage) {
+        this.sendList.offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopSend() {
+        Packet MyPackage = this.sendList.poll();
+        return MyPackage;
+    }
+
+    public void AppendToRece(Packet MyPackage) {
+        this.receList.offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopRece() {
+        Packet MyPackage = this.receList.poll();
+        return MyPackage;
+    }
+
+    public Packet takeRece() throws InterruptedException {
+        Packet MyPackage = this.receList.take();
+        return MyPackage;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 172 - 0
src/main/java/com/persagy/iottransfer/communication/nio/tcp/client/NIOTCPClientThread.java

@@ -0,0 +1,172 @@
+package com.persagy.iottransfer.communication.nio.tcp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.ExceptionUtil;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import com.persagy.iottransfer.communication.util.MyDecoder;
+import com.persagy.iottransfer.communication.util.MyEncoder;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+@Slf4j
+public class NIOTCPClientThread extends Thread {
+    private final ByteBuffer sendbuffer;
+    public NIOTCPClientManager manager;
+    MyEncoder encoder;
+    MyDecoder decoder;
+    private SocketChannel socketChannel;
+    private Selector selector;
+    private boolean stop = false;
+
+    public NIOTCPClientThread(NIOTCPClientManager manager) {
+        this.manager = manager;
+        this.sendbuffer = ByteBuffer.allocate(this.manager.buffer_size);
+
+        this.encoder = new MyEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password, manager.compress,
+                manager.separate, manager.separateBytes, manager.prefix, manager.suffix, manager.prefixBytes,
+                manager.suffixBytes);
+        this.decoder = new MyDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password, manager.compress,
+                manager.separate, manager.separateBytes, manager.prefix, manager.suffix, manager.prefixBytes,
+                manager.suffixBytes);
+    }
+
+    public void requestStop() {
+        this.stop = true;
+        try {
+            this.join();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void run() {
+        while (!this.stop) {
+            TryRun();
+        }
+    }
+
+    public void TryRun() {
+        try {
+            // ��ͨ��
+            this.socketChannel = SocketChannel.open();
+            // ����������
+            this.socketChannel.configureBlocking(false);
+            // ��Selector
+            this.selector = Selector.open();
+            // ���ӷ�����
+            InetSocketAddress serverAddress = new InetSocketAddress(this.manager.ip, this.manager.port);
+            this.socketChannel.connect(serverAddress);
+
+            // ע�������¼�����
+            this.socketChannel.register(this.selector, SelectionKey.OP_CONNECT);
+
+            this.manager.SetSessionClosed(false);
+            log.warn(this.manager.Name() + "\tStart");
+
+            this.listen();
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        } finally {
+            try {
+                this.socketChannel.close();
+                this.selector.close();
+                this.manager.SetSessionClosed(true);
+
+                log.warn(this.manager.Name() + "\tStop");
+            } catch (IOException e1) {
+                log.error(ExceptionUtil.Instance().GetMessage(e1));
+            }
+        }
+    }
+
+    private void listen() throws Exception {
+        int cycleNumber = 0;
+        while (!this.stop) {
+            // ������ֱ���¼�����
+            this.selector.select(this.manager.SelectTimeout);
+            // ��ȡ��ѡ�����
+            Set<SelectionKey> selectionKeys = this.selector.selectedKeys();
+            // ѭ�������¼�
+            Iterator<SelectionKey> iterator = selectionKeys.iterator();
+            while (iterator.hasNext()) {
+                SelectionKey selectionKey = iterator.next();
+                this.handleKey(selectionKey);
+            }
+            selectionKeys.clear();
+
+            cycleNumber++;
+            if (cycleNumber == this.manager.SleepCount) {
+                cycleNumber = 0;
+                try {
+                    Thread.sleep(1L);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private void handleKey(SelectionKey selectionKey) throws Exception {
+        if (selectionKey.isConnectable()) {
+            SocketChannel client = (SocketChannel) selectionKey.channel();
+            // �������
+            if (client.isConnectionPending()) {
+                client.finishConnect();
+            }
+
+            client.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+        } else if (selectionKey.isReadable()) {
+            SocketChannel client = (SocketChannel) selectionKey.channel();
+            // ���������
+            ByteBuffer receivebuffer = ByteBuffer.allocate(this.manager.buffer_size);
+            // ��ȡ���ݵ���������
+            int count = client.read(receivebuffer);
+            if (count > 0) {
+                byte[] receiveBytes = receivebuffer.array();
+                byte[] bytesRece = new byte[count];
+                System.arraycopy(receiveBytes, 0, bytesRece, 0, count);
+
+                SocketAddress socketAddress = client.socket().getRemoteSocketAddress();
+                String remoteAddress = socketAddress.toString();
+                List<Packet> packetList = this.decoder.decode(remoteAddress, bytesRece);
+                for (int i = 0; i < packetList.size(); i++) {
+                    Packet packet = packetList.get(i);
+                    this.manager.AppendToRece(packet);
+
+                    if (this.manager.encoding != null) {
+                        log.info(this.manager.Name() + "\trece\t" + packet.packetString);
+                    } else {
+                        log.info(this.manager.Name() + "\trece\t" + HexToByte.byteToHex(packet.packetBytes));
+                    }
+                }
+            }
+        } else if (selectionKey.isWritable()) {
+            SocketChannel client = (SocketChannel) selectionKey.channel();
+            Packet packet = this.manager.PopSend();
+            if (packet != null) {
+                byte[] comm_bytes = this.encoder.encode(packet);
+                this.sendbuffer.clear();
+                this.sendbuffer.put(comm_bytes);
+                // ������������־��λ,��Ϊput���ݺ��־���ı�
+                this.sendbuffer.flip();
+                client.write(this.sendbuffer);
+
+                if (this.manager.encoding != null) {
+                    log.info(this.manager.Name() + "\tsend\t" + packet.packetString);
+                } else {
+                    log.info(this.manager.Name() + "\tsend\t" + HexToByte.byteToHex(packet.packetBytes));
+                }
+            }
+        }
+    }
+}

+ 219 - 0
src/main/java/com/persagy/iottransfer/communication/nio/tcp/server/NIOTCPServerManager.java

@@ -0,0 +1,219 @@
+package com.persagy.iottransfer.communication.nio.tcp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.util.ILogger;
+import com.persagy.iottransfer.communication.util.IServerHandler;
+import com.persagy.iottransfer.communication.util.IServerManager;
+import com.persagy.iottransfer.communication.util.PacketBuffer;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class NIOTCPServerManager implements IServerManager {
+    int buffer_size = 1024 * 16;
+    long SelectTimeout = 1L;
+    int SleepCount = 1000;
+
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+    int Max_size = 1000;
+
+    boolean separate;
+    boolean separateBytes;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    public final Map<String, Date> connectDateMap = new HashMap<String, Date>();
+    public final Map<String, PacketBuffer<Packet>> sendListMap = new HashMap<String, PacketBuffer<Packet>>();
+    public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+
+    NIOTCPServerThread thread;
+
+    ILogger logger;
+    int remark_count = 0;
+
+    public NIOTCPServerManager(String ip, int port, String encoding, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NIOTCPServerManager(String ip, int port, String encoding, int Max_size, byte prefix, byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NIOTCPServerManager(String ip, int port, String encoding, int Max_size, byte[] prefixBytes,
+                               byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NIOTCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = false;
+    }
+
+    public NIOTCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size, byte prefix,
+                               byte suffix) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+    }
+
+    public NIOTCPServerManager(String ip, int port, String encoding, boolean compress, int Max_size, byte[] prefixBytes,
+                               byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public NIOTCPServerManager(String ip, int port, String encoding, String aes_password, boolean compress,
+                               int Max_size, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.Max_size = Max_size;
+
+        this.separate = true;
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+    }
+
+    public void setHandlerManager(IServerHandler handlerManager) {
+    }
+
+    public String Name() {
+        return "TCP Server " + this.ip + ":" + this.port + " NIO";
+    }
+
+    public synchronized void Start() {
+        if (this.thread == null) {
+            this.thread = new NIOTCPServerThread(this);
+            this.thread.start();
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new PacketEntity(), Integer.MAX_VALUE);
+        }
+        if (this.thread != null) {
+            this.thread.requestStop();
+            this.thread = null;
+        }
+    }
+
+    public synchronized void AllowJustSend_UDP(boolean allow) {
+
+    }
+
+    public synchronized String[] GetClientAddresss() {
+        return this.connectDateMap.keySet().toArray(new String[0]);
+    }
+
+    public synchronized Date GetConnectTime(String clientAddress) {
+        if (this.connectDateMap.containsKey(clientAddress)) {
+            return this.connectDateMap.get(clientAddress);
+        }
+        return null;
+    }
+
+    public synchronized void SetConnectTime(String clientAddress, Date date) {
+        this.connectDateMap.remove(clientAddress);
+        if (date != null) {
+            this.connectDateMap.put(clientAddress, date);
+        }
+    }
+
+    public void AppendToSend(String clientAddress, Packet MyPackage) {
+        if (!this.sendListMap.containsKey(clientAddress)) {
+            this.sendListMap.put(clientAddress, new PacketBuffer<Packet>());
+        }
+        this.sendListMap.get(clientAddress).offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopSend(String clientAddress) {
+        if (!this.sendListMap.containsKey(clientAddress)) {
+            return null;
+        }
+
+        PacketBuffer<Packet> sendList = this.sendListMap.get(clientAddress);
+        Packet MyPackage = sendList.poll();
+        return MyPackage;
+    }
+
+    public void AppendToRece(String clientAddress, Packet MyPackage) {
+        PacketEntity entity = new PacketEntity();
+        entity.address = clientAddress;
+        entity.content = MyPackage;
+        this.receList.offer(entity, this.Max_size);
+    }
+
+    public PacketEntity PopRece() {
+        PacketEntity entity = this.receList.poll();
+        return entity;
+    }
+
+    public PacketEntity takeRece() throws InterruptedException {
+        PacketEntity entity = this.receList.take();
+        return entity;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void closeClient(String clientAddress) {
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 224 - 0
src/main/java/com/persagy/iottransfer/communication/nio/tcp/server/NIOTCPServerThread.java

@@ -0,0 +1,224 @@
+package com.persagy.iottransfer.communication.nio.tcp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.ExceptionUtil;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import com.persagy.iottransfer.communication.util.MyDecoder;
+import com.persagy.iottransfer.communication.util.MyEncoder;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+@Slf4j
+public class NIOTCPServerThread extends Thread {
+    private final ByteBuffer sendbuffer;
+    public NIOTCPServerManager manager;
+    MyEncoder encoder;
+    MyDecoder decoder;
+    private ServerSocketChannel serverSocketChannel;
+    private ServerSocket serverSocket;
+    private Selector selector;
+    private boolean stop = false;
+
+    public NIOTCPServerThread(NIOTCPServerManager manager) {
+        this.manager = manager;
+        this.sendbuffer = ByteBuffer.allocate(this.manager.buffer_size);
+
+        this.encoder = new MyEncoder(manager.ip, manager.port, manager.encoding, manager.aes_password, manager.compress,
+                manager.separate, manager.separateBytes, manager.prefix, manager.suffix, manager.prefixBytes,
+                manager.suffixBytes);
+        this.decoder = new MyDecoder(manager.ip, manager.port, manager.encoding, manager.aes_password, manager.compress,
+                manager.separate, manager.separateBytes, manager.prefix, manager.suffix, manager.prefixBytes,
+                manager.suffixBytes);
+    }
+
+    public void requestStop() {
+        this.stop = true;
+        try {
+            this.join();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void run() {
+        while (!this.stop) {
+            TryRun();
+        }
+    }
+
+    public void TryRun() {
+        try {
+            // ���׽���ͨ��
+            this.serverSocketChannel = ServerSocketChannel.open();
+            // ����������
+            this.serverSocketChannel.configureBlocking(false);
+            // ��ȡͨ�����׽���
+            this.serverSocket = this.serverSocketChannel.socket();
+            // ��
+            InetSocketAddress serverAddress = new InetSocketAddress(InetAddress.getByName(this.manager.ip),
+                    this.manager.port);
+            this.serverSocket.bind(serverAddress);
+            // ��Selector
+            this.selector = Selector.open();
+            // ע�������¼�����
+            this.serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
+
+            log.warn(this.manager.Name() + "\tStart");
+
+            listen();
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        } finally {
+            try {
+                this.selector.close();
+                this.serverSocket.close();
+                this.serverSocketChannel.close();
+
+                log.warn(this.manager.Name() + "\tStop");
+            } catch (IOException e1) {
+                log.error(ExceptionUtil.Instance().GetMessage(e1));
+            }
+        }
+    }
+
+    private void listen() throws IOException {
+        int cycleNumber = 0;
+        while (!this.stop) {
+            // ������ֱ���¼�����
+            this.selector.select(this.manager.SelectTimeout);
+            // ��ȡ��ѡ�����
+            Set<SelectionKey> selectionKeys = this.selector.selectedKeys();
+            // ѭ�������¼�
+            Iterator<SelectionKey> iterator = selectionKeys.iterator();
+            while (iterator.hasNext()) {
+                SelectionKey selectionKey = iterator.next();
+                handleKey(selectionKey);
+            }
+            selectionKeys.clear();
+
+            cycleNumber++;
+            if (cycleNumber == this.manager.SleepCount) {
+                cycleNumber = 0;
+                try {
+                    Thread.sleep(1L);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private void handleKey(SelectionKey selectionKey) {
+        SocketChannel channel = null;
+        if (selectionKey.isAcceptable()) {
+            ServerSocketChannel serverChannel = (ServerSocketChannel) selectionKey.channel();
+
+            try {
+                // �����ͻ�������
+                channel = serverChannel.accept();
+                // ����������
+                channel.configureBlocking(false);
+                // ע���¼�����
+                channel.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+
+                SocketAddress socketAddress = channel.socket().getRemoteSocketAddress();
+                String remoteAddress = socketAddress.toString();
+                this.manager.SetConnectTime(remoteAddress, new Date());
+                log.warn(this.manager.Name() + "\taccept\t" + remoteAddress);
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+                try {
+                    channel.close();
+                } catch (Exception e1) {
+                    log.error(ExceptionUtil.Instance().GetMessage(e1));
+                }
+            }
+        } else if (selectionKey.isReadable()) {
+            // ��ȡ�ͻ�������
+            channel = (SocketChannel) selectionKey.channel();
+
+            try {
+                SocketAddress socketAddress = channel.socket().getRemoteSocketAddress();
+                String remoteAddress = socketAddress.toString();
+                // ��ջ�����
+                ByteBuffer receivebuffer = ByteBuffer.allocate(this.manager.buffer_size);
+                // ��ȡ���ݵ���������
+                int count = channel.read(receivebuffer);
+                if (count > 0) {
+                    byte[] receiveBytes = receivebuffer.array();
+                    byte[] bytesRece = new byte[count];
+                    System.arraycopy(receiveBytes, 0, bytesRece, 0, count);
+
+                    List<Packet> packetList = this.decoder.decode(remoteAddress, bytesRece);
+                    for (int i = 0; i < packetList.size(); i++) {
+                        Packet packet = packetList.get(i);
+                        this.manager.AppendToRece(remoteAddress, packet);
+
+                        if (this.manager.encoding != null) {
+                            log.info(this.manager.Name() + "\trece\t"
+                                    + socketAddress + "\t" + packet.packetString);
+                        } else {
+                            log.info(this.manager.Name() + "\trece\t"
+                                    + socketAddress + "\t" + HexToByte.byteToHex(packet.packetBytes));
+                        }
+                    }
+                } else if (count == -1) {
+                    channel.close();
+                    log.warn(this.manager.Name() + "\tclose\t" + remoteAddress);
+                }
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+                try {
+                    channel.close();
+                } catch (Exception e1) {
+                    log.error(ExceptionUtil.Instance().GetMessage(e1));
+                }
+            }
+        } else if (selectionKey.isWritable()) {
+            // ��ȡ�ͻ�������
+            channel = (SocketChannel) selectionKey.channel();
+
+            try {
+                SocketAddress socketAddress = channel.socket().getRemoteSocketAddress();
+                Packet packet = this.manager.PopSend(socketAddress.toString());
+                if (packet != null) {
+                    byte[] comm_bytes = this.encoder.encode(packet);
+                    this.sendbuffer.clear();
+                    this.sendbuffer.put(comm_bytes);
+                    // ������������־��λ,��Ϊput���ݺ��־���ı�
+                    this.sendbuffer.flip();
+                    channel.write(this.sendbuffer);
+
+                    if (this.manager.encoding != null) {
+                        log.info(this.manager.Name() + "\tsend\t"
+                                + socketAddress + "\t" + packet.packetString);
+                    } else {
+                        log.info(this.manager.Name() + "\tsend\t"
+                                + socketAddress + "\t" + HexToByte.byteToHex(packet.packetBytes));
+                    }
+                }
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+                try {
+                    channel.close();
+                } catch (Exception e1) {
+                    log.error(ExceptionUtil.Instance().GetMessage(e1));
+                }
+            }
+        }
+    }
+}

+ 115 - 0
src/main/java/com/persagy/iottransfer/communication/nio/udp/client/NIOUDPClientManager.java

@@ -0,0 +1,115 @@
+package com.persagy.iottransfer.communication.nio.udp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.IClientHandler;
+import com.persagy.iottransfer.communication.util.IClientManager;
+import com.persagy.iottransfer.communication.util.PacketBuffer;
+import com.persagy.iottransfer.config.IotProperties;
+
+public class NIOUDPClientManager implements IClientManager {
+    String ip;
+    IotProperties.Client client;
+    String projectId;
+    int port;
+    String targetIp;
+    int targetPort;
+    String encoding;
+    int buffer_size = 1024 * 16;
+
+    int Max_size = 1000;
+    long SelectTimeout = 1L;
+    int SleepCount = 1000;
+
+    boolean sessionClosed = false;
+
+    public final PacketBuffer<Packet> sendList = new PacketBuffer<Packet>();
+    public final PacketBuffer<Packet> receList = new PacketBuffer<Packet>();
+
+    NIOUDPClientThread thread;
+    int remark_count = 0;
+
+    public NIOUDPClientManager(String ip, int port, String targetIp, int targetPort, String encoding, int buffer_size,
+                               int Max_size, long SelectTimeout, int SleepCount) {
+        this.ip = ip;
+        this.port = port;
+        this.targetIp = targetIp;
+        this.targetPort = targetPort;
+        this.encoding = encoding;
+        this.buffer_size = buffer_size;
+
+        this.Max_size = Max_size;
+        this.SelectTimeout = SelectTimeout;
+        this.SleepCount = SleepCount;
+    }
+
+    public void setHandlerManager(IClientHandler handlerManager) {
+    }
+
+    public String Name() {
+        return "UDP Client " + this.ip + ":" + this.port + " NIO";
+    }
+
+    public synchronized boolean IsSessionClosed() {
+        return this.sessionClosed;
+    }
+
+    public synchronized void SetSessionClosed(boolean value) {
+        this.sessionClosed = value;
+    }
+
+    public synchronized void Start() {
+        if (this.thread == null) {
+            this.thread = new NIOUDPClientThread(this);
+            this.thread.start();
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new Packet(), Integer.MAX_VALUE);
+        }
+        if (this.thread != null) {
+            this.thread.requestStop();
+            this.thread = null;
+        }
+    }
+
+    public void AppendToSend(Packet MyPackage) {
+        this.sendList.offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopSend() {
+        Packet MyPackage = this.sendList.poll();
+        return MyPackage;
+    }
+
+    public void AppendToRece(Packet MyPackage) {
+        this.receList.offer(MyPackage, this.Max_size);
+    }
+
+    public Packet PopRece() {
+        Packet MyPackage = this.receList.poll();
+        return MyPackage;
+    }
+
+    public Packet takeRece() throws InterruptedException {
+        Packet MyPackage = this.receList.take();
+        return MyPackage;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+    @Override
+    public String getProjectId() {
+        return this.projectId;
+    }
+    @Override
+    public IotProperties.Client getClient() {
+        return this.client;
+    }
+}

+ 149 - 0
src/main/java/com/persagy/iottransfer/communication/nio/udp/client/NIOUDPClientThread.java

@@ -0,0 +1,149 @@
+package com.persagy.iottransfer.communication.nio.udp.client;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.util.ExceptionUtil;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.util.Iterator;
+import java.util.Set;
+
+@Slf4j
+public class NIOUDPClientThread extends Thread {
+    private final ByteBuffer sendbuffer;
+    public NIOUDPClientManager manager;
+    private SocketAddress targetAddress;
+    private DatagramChannel serverSocketChannel;
+    private Selector selector;
+    private boolean stop = false;
+
+    public NIOUDPClientThread(NIOUDPClientManager manager) {
+        this.manager = manager;
+        this.sendbuffer = ByteBuffer.allocate(this.manager.buffer_size);
+    }
+
+    public void requestStop() {
+        this.stop = true;
+        try {
+            this.join();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void run() {
+        while (!this.stop) {
+            TryRun();
+        }
+    }
+
+    public void TryRun() {
+        try {
+            // ���׽���ͨ��
+            this.serverSocketChannel = DatagramChannel.open();
+            // ����������
+            this.serverSocketChannel.configureBlocking(false);
+            // ��ȡͨ�����׽���
+            DatagramSocket serverSocket = this.serverSocketChannel.socket();
+            // ��
+            InetSocketAddress serverAddress = new InetSocketAddress(InetAddress.getByName(this.manager.ip),
+                    this.manager.port);
+            serverSocket.bind(serverAddress);
+            // ��Selector
+            this.selector = Selector.open();
+            // ע�������¼�����
+            this.serverSocketChannel.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+
+            this.targetAddress = new InetSocketAddress(InetAddress.getByName(this.manager.targetIp),
+                    this.manager.targetPort);
+
+            this.manager.SetSessionClosed(false);
+            log.warn(this.manager.Name() + "\tStart");
+
+            this.listen();
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        } finally {
+            try {
+                this.serverSocketChannel.close();
+                this.selector.close();
+                this.manager.SetSessionClosed(true);
+
+                log.warn(this.manager.Name() + "\tStop");
+            } catch (IOException e1) {
+                log.error(ExceptionUtil.Instance().GetMessage(e1));
+            }
+        }
+    }
+
+    private void listen() throws IOException {
+        int cycleNumber = 0;
+        while (!this.stop) {
+            this.selector.select(this.manager.SelectTimeout);
+            Set<SelectionKey> selectionKeys = this.selector.selectedKeys();
+            Iterator<SelectionKey> iterator = selectionKeys.iterator();
+            while (iterator.hasNext()) {
+                SelectionKey selectionKey = iterator.next();
+                handleKey(selectionKey);
+            }
+            selectionKeys.clear();
+
+            cycleNumber++;
+            if (cycleNumber == this.manager.SleepCount) {
+                cycleNumber = 0;
+                try {
+                    Thread.sleep(1L);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public void handleKey(SelectionKey selectionKey) throws IOException {
+        if (selectionKey.isReadable()) {
+            DatagramChannel client = (DatagramChannel) selectionKey.channel();
+
+            ByteBuffer receivebuffer = ByteBuffer.allocate(this.manager.buffer_size);
+            client.receive(receivebuffer);
+            byte[] bytesRece = receivebuffer.array();
+
+            if (this.manager.encoding == null) {
+                Packet packet = new Packet(bytesRece);
+                this.manager.AppendToRece(packet);
+                log.info(this.manager.Name() + "\trece\t" + HexToByte.byteToHex(packet.packetBytes));
+            } else {
+                String MyPackage = new String(bytesRece, this.manager.encoding);
+                MyPackage = MyPackage.trim();
+                Packet packet = new Packet(MyPackage);
+                this.manager.AppendToRece(packet);
+                log.info(this.manager.Name() + "\trece\t" + packet.packetString);
+            }
+        } else if (selectionKey.isWritable()) {
+            DatagramChannel client = (DatagramChannel) selectionKey.channel();
+            Packet packet = this.manager.PopSend();
+            if (packet != null) {
+                this.sendbuffer.clear();
+                if (this.manager.encoding == null) {
+                    this.sendbuffer.put(packet.packetBytes);
+                    log.info(
+                            this.manager.Name() + "\tsend\t" + HexToByte.byteToHex(packet.packetBytes));
+                } else {
+                    this.sendbuffer.put(packet.packetString.getBytes(this.manager.encoding));
+                    log.info(this.manager.Name() + "\tsend\t" + packet.packetString);
+                }
+                this.sendbuffer.flip();
+                client.send(this.sendbuffer, this.targetAddress);
+            }
+        }
+    }
+}

+ 157 - 0
src/main/java/com/persagy/iottransfer/communication/nio/udp/server/NIOUDPServerManager.java

@@ -0,0 +1,157 @@
+package com.persagy.iottransfer.communication.nio.udp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.entity.UDPSendEntity;
+import com.persagy.iottransfer.communication.util.IServerHandler;
+import com.persagy.iottransfer.communication.util.IServerManager;
+import com.persagy.iottransfer.communication.util.PacketBuffer;
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+public class NIOUDPServerManager implements IServerManager {
+    String ip;
+    int port;
+    String encoding;
+    int buffer_size = 1024 * 16;
+
+    int Max_size = 1000;
+    long SelectTimeout = 1L;
+    int SleepCount = 1000;
+
+    public final Map<String, Date> connectDateMap = new HashMap<String, Date>();
+    public final Map<String, SocketAddress> socketMap = new HashMap<String, SocketAddress>();
+    public final PacketBuffer<PacketEntity> sendList = new PacketBuffer<PacketEntity>();
+    public final PacketBuffer<PacketEntity> receList = new PacketBuffer<PacketEntity>();
+
+    NIOUDPServerThread thread;
+
+    boolean allowJustSend = false;
+    int remark_count = 0;
+
+    public NIOUDPServerManager(String ip, int port, String encoding, int buffer_size, int Max_size, long SelectTimeout,
+                               int SleepCount) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.buffer_size = buffer_size;
+
+        this.Max_size = Max_size;
+        this.SelectTimeout = SelectTimeout;
+        this.SleepCount = SleepCount;
+    }
+
+    public void setHandlerManager(IServerHandler handlerManager) {
+    }
+
+    public String Name() {
+        return "UDP Server " + this.ip + ":" + this.port + " NIO";
+    }
+
+    public synchronized void Start() {
+        if (this.thread == null) {
+            this.thread = new NIOUDPServerThread(this);
+            this.thread.start();
+        }
+    }
+
+    public synchronized void Stop() {
+        for (int i = 0; i < this.remark_count; i++) {
+            this.receList.offer(new PacketEntity(), Integer.MAX_VALUE);
+        }
+        if (this.thread != null) {
+            this.thread.requestStop();
+            this.thread = null;
+        }
+    }
+
+    public synchronized String[] GetClientAddresss() {
+        return this.connectDateMap.keySet().toArray(new String[0]);
+    }
+
+    public synchronized void AllowJustSend_UDP(boolean allow) {
+        this.allowJustSend = allow;
+    }
+
+    public synchronized Date GetConnectTime(String clientAddress) {
+        if (this.connectDateMap.containsKey(clientAddress)) {
+            return this.connectDateMap.get(clientAddress);
+        }
+        return null;
+    }
+
+    public synchronized void SetConnectTime(String clientAddress, Date date) {
+        this.connectDateMap.remove(clientAddress);
+        if (date != null) {
+            this.connectDateMap.put(clientAddress, date);
+        }
+    }
+
+    public synchronized void AddSocket(SocketAddress sa) {
+        String serverAddress = sa.toString();
+        if (!this.socketMap.containsKey(serverAddress)) {
+            this.socketMap.put(serverAddress, sa);
+        }
+    }
+
+    public void AppendToSend(String clientAddress, Packet MyPackage) {
+        PacketEntity entity = new PacketEntity();
+        entity.address = clientAddress;
+        entity.content = MyPackage;
+        this.sendList.offer(entity, this.Max_size);
+    }
+
+    public UDPSendEntity PopSend() {
+        PacketEntity entity = sendList.poll();
+        if (entity != null) {
+            if (this.allowJustSend && !this.socketMap.containsKey(entity.address)) {
+                int index = entity.address.indexOf(':');
+                String remote_ip = entity.address.substring(1, index);
+                int remote_port = Integer.parseInt(entity.address.substring(index + 1));
+                this.socketMap.put(entity.address, new InetSocketAddress(remote_ip, remote_port));
+            }
+            UDPSendEntity result = new UDPSendEntity();
+            result.address = this.socketMap.get(entity.address);
+            result.content = entity.content;
+            return result;
+        }
+        return null;
+    }
+
+    public void AppendToRece(SocketAddress sa, Packet MyPackage) {
+        String clientAddress = sa.toString();
+        if (!this.socketMap.containsKey(clientAddress)) {
+            this.socketMap.put(clientAddress, sa);
+        }
+        PacketEntity entity = new PacketEntity();
+        entity.address = clientAddress;
+        entity.content = MyPackage;
+        this.receList.offer(entity, this.Max_size);
+    }
+
+    public PacketEntity PopRece() {
+        PacketEntity entity = this.receList.poll();
+        return entity;
+    }
+
+    public PacketEntity takeRece() throws InterruptedException {
+        PacketEntity entity = this.receList.take();
+        return entity;
+    }
+
+    public int ReceBufferSize() {
+        return this.receList.BufferSize();
+    }
+
+    public synchronized void closeClient(String clientAddress) {
+        this.socketMap.remove(clientAddress);
+    }
+
+    public synchronized void hasRemark(int count) {
+        remark_count = count;
+    }
+}

+ 161 - 0
src/main/java/com/persagy/iottransfer/communication/nio/udp/server/NIOUDPServerThread.java

@@ -0,0 +1,161 @@
+package com.persagy.iottransfer.communication.nio.udp.server;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.UDPSendEntity;
+import com.persagy.iottransfer.communication.util.ExceptionUtil;
+import com.persagy.iottransfer.communication.util.HexToByte;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.util.Iterator;
+import java.util.Set;
+
+@Slf4j
+public class NIOUDPServerThread extends Thread {
+    private final ByteBuffer sendbuffer;
+    public NIOUDPServerManager manager;
+    private DatagramChannel serverSocketChannel;
+    private DatagramSocket serverSocket;
+    private Selector selector;
+    private boolean stop = false;
+
+    public NIOUDPServerThread(NIOUDPServerManager NIOUDPServerManager) {
+        this.manager = NIOUDPServerManager;
+        this.sendbuffer = ByteBuffer.allocate(this.manager.buffer_size);
+    }
+
+    public void requestStop() {
+        this.stop = true;
+        try {
+            this.join();
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void run() {
+        while (!this.stop) {
+            TryRun();
+        }
+    }
+
+    public void TryRun() {
+        try {
+            // ���׽���ͨ��
+            this.serverSocketChannel = DatagramChannel.open();
+            // ����������
+            this.serverSocketChannel.configureBlocking(false);
+            // ��ȡͨ�����׽���
+            this.serverSocket = this.serverSocketChannel.socket();
+            // ��
+            InetSocketAddress serverAddress = new InetSocketAddress(InetAddress.getByName(this.manager.ip),
+                    this.manager.port);
+            this.serverSocket.bind(serverAddress);
+            // ��Selector
+            this.selector = Selector.open();
+            // ע�������¼�����
+            this.serverSocketChannel.register(this.selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+
+            log.warn(this.manager.Name() + "\tStart");
+
+            listen();
+        } catch (Exception e) {
+            log.error(ExceptionUtil.Instance().GetMessage(e));
+        } finally {
+            try {
+                this.selector.close();
+                this.serverSocket.close();
+                this.serverSocketChannel.close();
+
+                log.warn(this.manager.Name() + "\tStop");
+            } catch (IOException e1) {
+                log.error(ExceptionUtil.Instance().GetMessage(e1));
+            }
+        }
+    }
+
+    private void listen() throws IOException {
+        int cycleNumber = 0;
+        while (!this.stop) {
+            // ������ֱ���¼�����
+            this.selector.select(this.manager.SelectTimeout);
+            // ��ȡ��ѡ�����
+            Set<SelectionKey> selectionKeys = this.selector.selectedKeys();
+            // ѭ�������¼�
+            Iterator<SelectionKey> iterator = selectionKeys.iterator();
+            while (iterator.hasNext()) {
+                SelectionKey selectionKey = iterator.next();
+                handleKey(selectionKey);
+            }
+            selectionKeys.clear();
+
+            cycleNumber++;
+            if (cycleNumber == this.manager.SleepCount) {
+                cycleNumber = 0;
+                try {
+                    Thread.sleep(1L);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    private void handleKey(SelectionKey selectionKey) throws IOException {
+        DatagramChannel channel = null;
+        if (selectionKey.isReadable()) {
+            // ��ȡ�ͻ�������
+            channel = (DatagramChannel) selectionKey.channel();
+            // ��ջ�����
+            ByteBuffer receivebuffer = ByteBuffer.allocate(this.manager.buffer_size);
+            // ��ȡ���ݵ���������
+            SocketAddress socketAddress = channel.receive(receivebuffer);
+            byte[] bytesRece = receivebuffer.array();
+
+            if (this.manager.encoding == null) {
+                Packet packet = new Packet(bytesRece);
+                this.manager.AppendToRece(socketAddress, packet);
+                log.info(
+                        this.manager.Name() + "\trece\t" + socketAddress + "\t"
+                                + HexToByte.byteToHex(packet.packetBytes));
+            } else {
+                String MyPackage = new String(bytesRece, this.manager.encoding);
+                MyPackage = MyPackage.trim();
+                Packet packet = new Packet(MyPackage);
+                this.manager.AppendToRece(socketAddress, packet);
+                log.info(
+                        this.manager.Name() + "\trece\t" + socketAddress + "\t" + packet.packetString);
+            }
+        } else if (selectionKey.isWritable()) {
+            // ��ȡ�ͻ�������
+            channel = (DatagramChannel) selectionKey.channel();
+
+            UDPSendEntity entity = this.manager.PopSend();
+            if (entity != null) {
+                this.sendbuffer.clear();
+                if (this.manager.encoding == null) {
+                    this.sendbuffer.put(entity.content.packetBytes);
+                    log.info(
+                            this.manager.Name() + "\tsend\t" + entity.address.toString() + "\t"
+                                    + HexToByte.byteToHex(entity.content.packetBytes));
+                } else {
+                    this.sendbuffer.put(entity.content.packetString.getBytes(this.manager.encoding));
+                    log.info(
+                            this.manager.Name() + "\tsend\t" + entity.address.toString() + "\t"
+                                    + entity.content.packetString);
+                }
+                // ������������־��λ,��Ϊput���ݺ��־���ı�
+                this.sendbuffer.flip();
+                channel.send(this.sendbuffer, entity.address);
+            }
+        }
+    }
+}

+ 56 - 0
src/main/java/com/persagy/iottransfer/communication/util/AESHelper.java

@@ -0,0 +1,56 @@
+package com.persagy.iottransfer.communication.util;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class AESHelper {
+    private static final String KEY_ALGORITHM = "AES";
+    private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
+    private final String algorithm;
+    private final byte[] password;
+    private final String mode;
+    private Cipher cipher;
+
+    public AESHelper(String algorithm, byte[] password, String mode) throws Exception {
+        if (algorithm != null) {
+            this.algorithm = algorithm;
+        } else {
+            this.algorithm = DEFAULT_CIPHER_ALGORITHM;
+        }
+        this.password = password;
+        this.mode = mode;
+
+        if (this.mode.equals("encrypt")) {
+            this.cipher = this.initCipher(this.password, Cipher.ENCRYPT_MODE);
+        } else if (this.mode.equals("decrypt")) {
+            this.cipher = this.initCipher(this.password, Cipher.DECRYPT_MODE);
+        }
+    }
+
+    private Cipher initCipher(byte[] password, int CipherMode) throws Exception {
+        Cipher cipher = Cipher.getInstance(this.algorithm);
+        SecretKeySpec keySpec = new SecretKeySpec(password, KEY_ALGORITHM);
+        IvParameterSpec ivSpec = new IvParameterSpec(new byte[16]);
+        cipher.init(CipherMode, keySpec, ivSpec);
+        return cipher;
+    }
+
+    public synchronized byte[] encrypt(byte[] bytes) throws Exception {
+        if (this.mode.equals("encrypt")) {
+            byte[] results = this.cipher.doFinal(bytes);
+            return results;
+        } else {
+            return null;
+        }
+    }
+
+    public synchronized byte[] decrypt(byte[] bytes) throws Exception {
+        if (this.mode.equals("decrypt")) {
+            byte[] results = this.cipher.doFinal(bytes);
+            return results;
+        } else {
+            return null;
+        }
+    }
+}

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 182 - 0
src/main/java/com/persagy/iottransfer/communication/util/CompressUtil.java


+ 24 - 0
src/main/java/com/persagy/iottransfer/communication/util/ExceptionUtil.java

@@ -0,0 +1,24 @@
+package com.persagy.iottransfer.communication.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+public class ExceptionUtil {
+    private static final ExceptionUtil instance = new ExceptionUtil();
+
+    private ExceptionUtil() {
+
+    }
+
+    public synchronized static ExceptionUtil Instance() {
+        return instance;
+    }
+
+    public synchronized String GetMessage(Exception e) {
+        StringWriter stringWriter = new StringWriter();
+        PrintWriter printWriter = new PrintWriter(stringWriter);
+        e.printStackTrace(printWriter);
+        String error = stringWriter.getBuffer().toString();
+        return error;
+    }
+}

+ 41 - 0
src/main/java/com/persagy/iottransfer/communication/util/FileToByte.java

@@ -0,0 +1,41 @@
+package com.persagy.iottransfer.communication.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileInputStream;
+
+public class FileToByte {
+    public static byte[] file2byte(String filepath) throws Exception {
+        FileInputStream fis = null;
+        ByteArrayOutputStream baos = null;
+        try {
+            fis = new FileInputStream(filepath);
+            baos = new ByteArrayOutputStream();
+
+            int len;
+            byte[] buffer = new byte[1024];
+            while ((len = fis.read(buffer)) != -1) {
+                baos.write(buffer, 0, len);
+            }
+
+            byte[] bytes = baos.toByteArray();
+            return bytes;
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            if (fis != null) {
+                try {
+                    fis.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+            if (baos != null) {
+                try {
+                    baos.close();
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+}

+ 114 - 0
src/main/java/com/persagy/iottransfer/communication/util/HexToByte.java

@@ -0,0 +1,114 @@
+package com.persagy.iottransfer.communication.util;
+
+import java.util.List;
+
+public class HexToByte {
+    public synchronized static byte[] hexToByte(String hex) {
+        return hexToByte(hex, false);
+    }
+
+    public synchronized static byte[] hexToByte(String hex, boolean hasspace) {
+        byte[] result;
+
+        if (hasspace) {
+            result = new byte[(hex.length() + 1) / 3];
+            for (int i = 0; i < result.length; i++) {
+                result[i] = Integer.decode("0x" + hex.substring(i * 3, i * 3 + 2)).byteValue();
+            }
+        } else {
+            result = new byte[hex.length() / 2];
+            for (int i = 0; i < result.length; i++) {
+                result[i] = Integer.decode("0x" + hex.substring(i * 2, i * 2 + 2)).byteValue();
+            }
+        }
+        return result;
+    }
+
+    public synchronized static String byteToHex(byte[] bytes) {
+        return byteToHex(bytes, false);
+    }
+
+    public synchronized static String byteToHex(byte[] bytes, boolean hasspace) {
+        StringBuffer sb = new StringBuffer();
+
+        for (int i = 0; i < bytes.length; i++) {
+            if (hasspace && i > 0) {
+                sb.append(" ");
+            }
+            int temp = (bytes[i] + 256) % 256;
+            sb.append("" + getHexChar(temp / 16) + getHexChar(temp % 16));
+        }
+        return sb.toString();
+    }
+
+    public synchronized static String byteToHex(List<Byte> bytes) {
+        return byteToHex(bytes, false);
+    }
+
+    public synchronized static String byteToHex(List<Byte> bytes, boolean hasspace) {
+        StringBuffer sb = new StringBuffer();
+
+        for (int i = 0; i < bytes.size(); i++) {
+            if (hasspace && i > 0) {
+                sb.append(" ");
+            }
+            int temp = (bytes.get(i) + 256) % 256;
+            sb.append("" + getHexChar(temp / 16) + getHexChar(temp % 16));
+        }
+        return sb.toString();
+    }
+
+    public synchronized static String byteToHex(List<Byte> bytes, int length) {
+        return byteToHex(bytes, false);
+    }
+
+    public synchronized static String byteToHex(List<Byte> bytes, int length, boolean hasspace) {
+        StringBuffer sb = new StringBuffer();
+
+        for (int i = 0; i < length; i++) {
+            if (hasspace && i > 0) {
+                sb.append(" ");
+            }
+            int temp = (bytes.get(i) + 256) % 256;
+            sb.append("" + getHexChar(temp / 16) + getHexChar(temp % 16));
+        }
+        return sb.toString();
+    }
+
+    public synchronized static String byteToHex(byte[] bytes, int length) {
+        return byteToHex(bytes, false);
+    }
+
+    public synchronized static String byteToHex(byte[] bytes, int length, boolean hasspace) {
+        StringBuffer sb = new StringBuffer();
+
+        for (int i = 0; i < length; i++) {
+            if (hasspace && i > 0) {
+                sb.append(" ");
+            }
+            int temp = (bytes[i] + 256) % 256;
+            sb.append("" + getHexChar(temp / 16) + getHexChar(temp % 16));
+        }
+        return sb.toString();
+    }
+
+    private static String getHexChar(int number) {
+        String result;
+        if (number < 10) {
+            result = "" + number;
+        } else {
+            result = "" + (char) (number - 10 + 'A');
+        }
+        return result;
+    }
+
+    public synchronized static byte[] setVerify(byte[] bytes) {
+        int number = 0;
+        for (int i = 2; i < bytes.length - 2; i++) {
+            number += (bytes[i] + 256) % 256;
+        }
+        bytes[bytes.length - 2] = (byte) (number % 256);
+        bytes[bytes.length - 1] = (byte) (number / 256);
+        return bytes;
+    }
+}

+ 12 - 0
src/main/java/com/persagy/iottransfer/communication/util/IClientHandler.java

@@ -0,0 +1,12 @@
+package com.persagy.iottransfer.communication.util;
+
+public interface IClientHandler {
+    void sessionOpened() throws Exception;
+
+    void sessionClosed() throws Exception;
+
+    void exceptionCaught(Throwable cause) throws Exception;
+
+    void sessionIdle() throws Exception;
+
+}

+ 32 - 0
src/main/java/com/persagy/iottransfer/communication/util/IClientManager.java

@@ -0,0 +1,32 @@
+package com.persagy.iottransfer.communication.util;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.config.IotProperties;
+
+public interface IClientManager {
+    IotProperties.Client getClient();
+
+    String getProjectId();
+
+    String Name();
+
+    void Start();
+
+    void Stop();
+
+    boolean IsSessionClosed();
+
+    void SetSessionClosed(boolean value);
+
+    void AppendToSend(Packet MyPackage);
+
+    Packet PopRece();
+
+    Packet takeRece() throws InterruptedException;
+
+    int ReceBufferSize();
+
+    void setHandlerManager(IClientHandler handlerManager);
+
+    void hasRemark(int count);
+}

+ 13 - 0
src/main/java/com/persagy/iottransfer/communication/util/ILogger.java

@@ -0,0 +1,13 @@
+package com.persagy.iottransfer.communication.util;
+
+public interface ILogger {
+    void debug(String message);
+
+    void info(String message);
+
+    void warn(String message);
+
+    void error(String message);
+
+    void fatal(String message);
+}

+ 13 - 0
src/main/java/com/persagy/iottransfer/communication/util/IServerHandler.java

@@ -0,0 +1,13 @@
+package com.persagy.iottransfer.communication.util;
+
+import java.net.SocketAddress;
+
+public interface IServerHandler {
+    void sessionOpened(SocketAddress address) throws Exception;
+
+    void sessionClosed(SocketAddress address) throws Exception;
+
+    void exceptionCaught(SocketAddress address, Throwable cause) throws Exception;
+
+    void sessionIdle(SocketAddress address) throws Exception;
+}

+ 34 - 0
src/main/java/com/persagy/iottransfer/communication/util/IServerManager.java

@@ -0,0 +1,34 @@
+package com.persagy.iottransfer.communication.util;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+
+import java.util.Date;
+
+public interface IServerManager {
+    String Name();
+
+    void Start();
+
+    void Stop();
+
+    void AllowJustSend_UDP(boolean allow);
+
+    String[] GetClientAddresss();
+
+    Date GetConnectTime(String clientAddress);
+
+    void AppendToSend(String clientAddress, Packet MyPackage);
+
+    PacketEntity PopRece();
+
+    PacketEntity takeRece() throws InterruptedException;
+
+    int ReceBufferSize();
+
+    void setHandlerManager(IServerHandler handlerManager);
+
+    void closeClient(String clientAddress);
+
+    void hasRemark(int count);
+}

+ 157 - 0
src/main/java/com/persagy/iottransfer/communication/util/MyDecoder.java

@@ -0,0 +1,157 @@
+package com.persagy.iottransfer.communication.util;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.mina.codec.MinaCodecFactory;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.*;
+
+@Slf4j
+public class MyDecoder {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+
+    boolean separate = false;
+    boolean separateBytes = false;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    Byte[] forbid_bytes;
+
+    AESHelper aes;
+    Map<String, MyStream> streamMap = new HashMap<String, MyStream>();
+    Long last_minute = null;
+    int info_minute = 0;
+    int comm_minute = 0;
+    int count_minute = 0;
+    Long last_hour = null;
+    int info_hour = 0;
+    int comm_hour = 0;
+    int count_hour = 0;
+
+    public MyDecoder(String ip, int port, String encoding, String aes_password, boolean compress, boolean separate,
+                     boolean separateBytes, byte prefix, byte suffix, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.separate = separate || separateBytes;
+        this.separateBytes = separateBytes;
+        this.prefix = prefix;
+        this.suffix = suffix;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        if (this.aes_password != null) {
+            try {
+                this.aes = new AESHelper(null, HexToByte.hexToByte(this.aes_password), "decrypt");
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+        if (this.separate) {
+            List<Byte> byteList = new ArrayList<Byte>();
+            if (this.separateBytes) {
+                MinaCodecFactory.add_forbit_bytes(this.prefixBytes, byteList);
+                MinaCodecFactory.add_forbit_bytes(this.suffixBytes, byteList);
+            } else {
+                MinaCodecFactory.add_forbit_byte(this.prefix, byteList);
+                MinaCodecFactory.add_forbit_byte(this.suffix, byteList);
+            }
+            this.forbid_bytes = byteList.toArray(new Byte[0]);
+        }
+    }
+
+    public synchronized List<Packet> decode(String remoteAddress, byte[] rece_bytes) throws Exception {
+        List<Packet> result = new ArrayList<Packet>();
+
+        if (this.separate) {
+            if (!this.streamMap.containsKey(remoteAddress)) {
+                MyStream stream;
+                if (this.separateBytes) {
+                    stream = new MyStream(this.prefixBytes, this.suffixBytes);
+                } else {
+                    stream = new MyStream(this.prefix, this.suffix);
+                }
+                this.streamMap.put(remoteAddress, stream);
+            }
+            MyStream stream = this.streamMap.get(remoteAddress);
+            List<byte[]> bytesList = stream.Process(rece_bytes, rece_bytes.length);
+            for (int i = 0; i < bytesList.size(); i++) {
+                byte[] bytes = bytesList.get(i);
+                Packet packet = this.process_packet(bytes, stream.head_count);
+                result.add(packet);
+            }
+        } else {
+            Packet packet = this.process_packet(rece_bytes, 0);
+            result.add(packet);
+        }
+
+        return result;
+    }
+
+    public synchronized Packet process_packet(byte[] bytes, int head_count) throws Exception {
+        Date currentTime = new Date();
+
+        long curr_minute = currentTime.getTime() / (1000L * 60);
+        if (last_minute != null && last_minute != curr_minute) {
+            log.warn(this.ip + ":" + this.port + "\t" + "rece minute" + "\t" + info_minute + "\t" + comm_minute + "\t" + count_minute);
+        }
+        if (last_minute == null || last_minute != curr_minute) {
+            last_minute = curr_minute;
+            info_minute = 0;
+            comm_minute = 0;
+            count_minute = 0;
+        }
+
+        long curr_hour = currentTime.getTime() / (1000L * 60 * 60);
+        if (last_hour != null && last_hour != curr_hour) {
+            log.warn(this.ip + ":" + this.port + "\t" + "rece hour" + "\t" + info_hour + "\t" + comm_hour + "\t" + count_hour);
+        }
+        if (last_hour == null || last_hour != curr_hour) {
+            last_hour = curr_hour;
+            info_hour = 0;
+            comm_hour = 0;
+            count_hour = 0;
+        }
+
+        comm_minute += bytes.length + head_count;
+        comm_hour += bytes.length + head_count;
+
+        if (this.separate) {
+            bytes = CompressUtil.decode(bytes, this.forbid_bytes);
+        }
+        if (this.compress) {
+            bytes = CompressUtil.decompress(bytes);
+        }
+        if (this.aes_password != null) {
+            try {
+                bytes = this.aes.decrypt(bytes);
+            } catch (Exception e) {
+                log.error(e.getMessage(), e);
+                throw e;
+            }
+        }
+
+        info_minute += bytes.length;
+        info_hour += bytes.length;
+
+        count_minute++;
+        count_hour++;
+
+        Packet packet;
+        if (this.encoding != null) {
+            packet = new Packet(new String(bytes, this.encoding));
+        } else {
+            packet = new Packet(bytes);
+        }
+        return packet;
+    }
+
+}

+ 152 - 0
src/main/java/com/persagy/iottransfer/communication/util/MyEncoder.java

@@ -0,0 +1,152 @@
+package com.persagy.iottransfer.communication.util;
+
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.mina.codec.MinaCodecFactory;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+@Slf4j
+public class MyEncoder {
+    String ip;
+    int port;
+    String encoding;
+    String aes_password;
+    boolean compress = false;
+
+    boolean separate = false;
+    boolean separateBytes = false;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+
+    Byte[] forbid_bytes;
+
+    AESHelper aes;
+    Long last_minute = null;
+    long info_minute = 0;
+    long comm_minute = 0;
+    long count_minute = 0;
+    Long last_hour = null;
+    long info_hour = 0;
+    long comm_hour = 0;
+    long count_hour = 0;
+
+    public MyEncoder(String ip, int port, String encoding, String aes_password, boolean compress, boolean separate,
+                     boolean separateBytes, byte prefix, byte suffix, byte[] prefixBytes, byte[] suffixBytes) {
+        this.ip = ip;
+        this.port = port;
+        this.encoding = encoding;
+        this.aes_password = aes_password;
+        this.compress = compress;
+        this.separate = separate || separateBytes;
+        this.separateBytes = separateBytes;
+        this.prefix = prefix;
+        this.suffix = suffix;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        if (this.aes_password != null) {
+            try {
+                this.aes = new AESHelper(null, HexToByte.hexToByte(this.aes_password), "encrypt");
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+            }
+        }
+        if (this.separate) {
+            List<Byte> byteList = new ArrayList<Byte>();
+            if (this.separateBytes) {
+                MinaCodecFactory.add_forbit_bytes(this.prefixBytes, byteList);
+                MinaCodecFactory.add_forbit_bytes(this.suffixBytes, byteList);
+            } else {
+                MinaCodecFactory.add_forbit_byte(this.prefix, byteList);
+                MinaCodecFactory.add_forbit_byte(this.suffix, byteList);
+            }
+            this.forbid_bytes = byteList.toArray(new Byte[0]);
+        }
+    }
+
+    public synchronized byte[] encode(Packet request) throws Exception {
+        Date currentTime = new Date();
+
+        long curr_minute = currentTime.getTime() / (1000L * 60);
+        if (last_minute != null && last_minute != curr_minute) {
+            log.warn(this.ip + ":" + this.port + "\t" + "send minute" + "\t" + info_minute + "\t"
+                    + comm_minute + "\t" + count_minute);
+        }
+        if (last_minute == null || last_minute != curr_minute) {
+            last_minute = curr_minute;
+            info_minute = 0;
+            comm_minute = 0;
+            count_minute = 0;
+        }
+
+        long curr_hour = currentTime.getTime() / (1000L * 60 * 60);
+        if (last_hour != null && last_hour != curr_hour) {
+            log.warn(this.ip + ":" + this.port + "\t" + "send hour" + "\t" + info_hour + "\t"
+                    + comm_hour + "\t" + count_hour);
+        }
+        if (last_hour == null || last_hour != curr_hour) {
+            last_hour = curr_hour;
+            info_hour = 0;
+            comm_hour = 0;
+            count_hour = 0;
+        }
+
+        byte[] content_bytes;
+        if (this.encoding != null) {
+            content_bytes = request.packetString.getBytes(this.encoding);
+        } else {
+            content_bytes = request.packetBytes;
+        }
+        info_minute += content_bytes.length;
+        info_hour += content_bytes.length;
+
+        if (this.aes_password != null) {
+            try {
+                content_bytes = this.aes.encrypt(content_bytes);
+            } catch (Exception e) {
+                log.error(ExceptionUtil.Instance().GetMessage(e));
+                throw e;
+            }
+        }
+        if (this.compress) {
+            content_bytes = CompressUtil.compress(content_bytes);
+        }
+        if (this.separate) {
+            content_bytes = CompressUtil.encode(content_bytes, this.forbid_bytes);
+        }
+
+        int comm_length;
+        byte[] buffer;
+        if (this.separate) {
+            if (this.separateBytes) {
+                comm_length = this.prefixBytes.length + content_bytes.length + this.suffixBytes.length;
+                buffer = new byte[comm_length];
+                System.arraycopy(this.prefixBytes, 0, buffer, 0, this.prefixBytes.length);
+                System.arraycopy(content_bytes, 0, buffer, this.prefixBytes.length, content_bytes.length);
+                System.arraycopy(this.suffixBytes, 0, buffer, this.prefixBytes.length + content_bytes.length,
+                        this.suffixBytes.length);
+            } else {
+                comm_length = 1 + content_bytes.length + 1;
+                buffer = new byte[comm_length];
+                buffer[0] = this.prefix;
+                System.arraycopy(content_bytes, 0, buffer, 1, content_bytes.length);
+                buffer[1 + content_bytes.length] = this.suffix;
+            }
+        } else {
+            comm_length = content_bytes.length;
+            buffer = content_bytes;
+        }
+        comm_minute += comm_length;
+        comm_hour += comm_length;
+
+        count_minute++;
+        count_hour++;
+
+        return buffer;
+    }
+}

+ 92 - 0
src/main/java/com/persagy/iottransfer/communication/util/MySslContextFactory.java

@@ -0,0 +1,92 @@
+package com.persagy.iottransfer.communication.util;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.KeyStore;
+
+public final class MySslContextFactory {
+    public static SSLContext getContext(String PROTOCOL, String KeyStoreType, String algorithm, String path_km,
+                                        String path_tm, String password_km, String password_tm) throws Exception {
+        InputStream is_km = null;
+        InputStream is_tm = null;
+        if (path_km != null) {
+            is_km = new FileInputStream(path_km);
+        }
+        if (path_tm != null) {
+            is_tm = new FileInputStream(path_tm);
+        }
+        SSLContext SSLContext = getContext(PROTOCOL, KeyStoreType, algorithm, is_km, is_tm, password_km, password_tm);
+        return SSLContext;
+    }
+
+    public static SSLContext getContext(String PROTOCOL, String KeyStoreType, String algorithm, byte[] bytes_km,
+                                        byte[] bytes_tm, String password_km, String password_tm) throws Exception {
+        ByteArrayInputStream in = null;
+        ByteArrayInputStream tIN = null;
+        if (bytes_km != null) {
+            in = new ByteArrayInputStream(bytes_km);
+        }
+        if (bytes_tm != null) {
+            tIN = new ByteArrayInputStream(bytes_tm);
+        }
+        SSLContext SSLContext = getContext(PROTOCOL, KeyStoreType, algorithm, in, tIN, password_km, password_tm);
+        return SSLContext;
+    }
+
+    private static SSLContext getContext(String PROTOCOL, String KeyStoreType, String algorithm, InputStream is_km,
+                                         InputStream is_tm, String password_km, String password_tm) throws Exception {
+        SSLContext context;
+
+        try {
+            // ��Կ������
+            KeyManagerFactory kmf = null;
+            if (is_km != null) {
+                KeyStore ks = KeyStore.getInstance(KeyStoreType);
+                ks.load(is_km, password_km.toCharArray());
+
+                kmf = KeyManagerFactory.getInstance(algorithm);
+                kmf.init(ks, password_km.toCharArray());
+            }
+            // ���ο�
+            TrustManagerFactory tf = null;
+            if (is_tm != null) {
+                KeyStore tks = KeyStore.getInstance(KeyStoreType);
+                tks.load(is_tm, password_tm.toCharArray());
+                tf = TrustManagerFactory.getInstance(algorithm);
+                tf.init(tks);
+            }
+
+            context = SSLContext.getInstance(PROTOCOL);
+            // ��ʼ����������
+            context.init(kmf == null ? null : kmf.getKeyManagers(), tf == null ? null : tf.getTrustManagers(), null);
+
+        } catch (Exception e) {
+            throw new Error("Failed to initialize the SSLContext", e);
+        } finally {
+            if (is_km != null) {
+                try {
+                    is_km.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                is_km = null;
+            }
+
+            if (is_tm != null) {
+                try {
+                    is_tm.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+                is_tm = null;
+            }
+        }
+
+        return context;
+    }
+}

+ 118 - 0
src/main/java/com/persagy/iottransfer/communication/util/MyStream.java

@@ -0,0 +1,118 @@
+package com.persagy.iottransfer.communication.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class MyStream {
+    public int head_count = 0;
+    boolean separateBytes = false;
+    byte prefix;
+    byte suffix;
+    byte[] prefixBytes;
+    byte[] suffixBytes;
+    List<Byte> contents = new ArrayList<Byte>();
+    boolean content_valid = false;
+    List<Byte> buffer = new ArrayList<Byte>();
+
+    public MyStream(byte prefix, byte suffix) {
+        this.separateBytes = false;
+        this.prefix = prefix;
+        this.suffix = suffix;
+
+        this.head_count = 2;
+    }
+
+    public MyStream(byte[] prefixBytes, byte[] suffixBytes) {
+        this.separateBytes = true;
+        this.prefixBytes = prefixBytes;
+        this.suffixBytes = suffixBytes;
+
+        this.head_count = this.prefixBytes.length + this.suffixBytes.length;
+    }
+
+    public List<byte[]> Process(byte[] bytes, int length) {
+        List<byte[]> result = new ArrayList<byte[]>();
+        if (this.separateBytes) {
+            for (int i = 0; i < length; i++) {
+                this.buffer.add(bytes[i]);
+            }
+            while (true) {
+                int suffix_index = this.FindIndexForward(this.buffer, this.buffer.size(), this.suffixBytes);
+                if (suffix_index == -1) {
+                    break;
+                }
+                int prefix_index = this.FindIndexBackward(this.buffer, suffix_index, this.prefixBytes);
+                if (prefix_index != -1) {
+                    int bytes_length = suffix_index - prefix_index - this.prefixBytes.length;
+                    if (bytes_length > 0) {
+                        byte[] bytesInner = new byte[bytes_length];
+                        for (int ii = 0; ii < bytes_length; ii++) {
+                            bytesInner[ii] = this.buffer.get(prefix_index + this.prefixBytes.length + ii);
+                        }
+                        result.add(bytesInner);
+                    }
+                }
+                for (int ii = 0; ii < suffix_index + this.suffixBytes.length; ii++) {
+                    this.buffer.remove(0);
+                }
+            }
+        } else {
+            for (int i = 0; i < length; i++) {
+                byte onebyte = bytes[i];
+                if (onebyte == this.suffix) {
+                    if (this.content_valid && this.contents.size() > 0) {
+                        byte[] bytesInner = new byte[contents.size()];
+                        for (int ii = 0; ii < this.contents.size(); ii++) {
+                            bytesInner[ii] = this.contents.get(ii);
+                        }
+                        result.add(bytesInner);
+                    }
+                    this.contents.clear();
+                    this.content_valid = false;
+                } else if (onebyte == this.prefix) {
+                    this.contents.clear();
+                    this.content_valid = true;
+                } else {
+                    if (this.content_valid) {
+                        this.contents.add(onebyte);
+                    }
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private int FindIndexForward(List<Byte> byteList, int length, byte[] bytes) {
+        int result = -1;
+        for (int i = 0; i <= length - bytes.length; i++) {
+            if (this.Match(byteList, i, bytes)) {
+                result = i;
+                break;
+            }
+        }
+        return result;
+    }
+
+    private int FindIndexBackward(List<Byte> byteList, int length, byte[] bytes) {
+        int result = -1;
+        for (int i = length - bytes.length; i >= 0; i--) {
+            if (this.Match(byteList, i, bytes)) {
+                result = i;
+                break;
+            }
+        }
+        return result;
+    }
+
+    private boolean Match(List<Byte> byteList, int index, byte[] bytes) {
+        boolean match = true;
+        for (int i = 0; i < bytes.length; i++) {
+            if (byteList.get(index + i) != bytes[i]) {
+                match = false;
+                break;
+            }
+        }
+        return match;
+    }
+}

+ 46 - 0
src/main/java/com/persagy/iottransfer/communication/util/PacketBuffer.java

@@ -0,0 +1,46 @@
+package com.persagy.iottransfer.communication.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.concurrent.LinkedBlockingQueue;
+
+@Slf4j
+public class PacketBuffer<T> {
+    private final LinkedBlockingQueue<T> buffer = new LinkedBlockingQueue<T>();
+
+    public PacketBuffer() {
+    }
+
+    // put �����������������
+    // add ��������������쳣
+    // offer �����������������false
+    public void offer(T packet, int size) {
+        if (this.buffer.size() >= size) {
+            return;
+        }
+
+        this.buffer.offer(packet);
+    }
+
+    // take ��������ѿգ�����
+    // remove ��������ѿգ��쳣
+    // poll ��������ѿգ�����null
+    public T poll() {
+        T MyPackage = null;
+        try {
+            MyPackage = this.buffer.take();
+        } catch (InterruptedException e) {
+            log.error(e.getMessage(), e);
+        }
+        return MyPackage;
+    }
+
+    public T take() throws InterruptedException {
+        T MyPackage = this.buffer.take();
+        return MyPackage;
+    }
+
+    public int BufferSize() {
+        return this.buffer.size();
+    }
+}

+ 30 - 0
src/main/java/com/persagy/iottransfer/config/CollectServerProperties.java

@@ -0,0 +1,30 @@
+package com.persagy.iottransfer.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/26 15:22
+ */
+@Component
+@ConfigurationProperties(prefix = "iot.server.collect")
+@Data
+public class CollectServerProperties {
+    private Boolean tcp_enable;
+    private String tcp_bind_ip;
+    private Integer tcp_bind_port;
+
+    private Boolean udp_enable;
+    private String udp_bind_ip;
+    private Integer udp_bind_port;
+
+    private Integer max_size;
+    private Integer sleepcount;
+    private String separate_begin;
+    private String separate_end;
+    private Boolean compress;
+
+}

+ 30 - 0
src/main/java/com/persagy/iottransfer/config/ControlServerProperties.java

@@ -0,0 +1,30 @@
+package com.persagy.iottransfer.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/26 15:22
+ */
+@Component
+@ConfigurationProperties(prefix = "iot.server.control")
+@Data
+public class ControlServerProperties {
+    private Boolean tcp_enable;
+    private String tcp_bind_ip;
+    private Integer tcp_bind_port;
+
+    private Boolean udp_enable;
+    private String udp_bind_ip;
+    private Integer udp_bind_port;
+
+    private Integer max_size;
+    private Integer sleepcount;
+    private String separate_begin;
+    private String separate_end;
+    private Boolean compress;
+
+}

+ 48 - 0
src/main/java/com/persagy/iottransfer/config/IotProperties.java

@@ -0,0 +1,48 @@
+package com.persagy.iottransfer.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/26 15:22
+ */
+@Component
+@ConfigurationProperties(prefix = "iot")
+@Data
+public class IotProperties {
+
+    public ArrayList<Client> clients;
+    public ArrayList<Project> projects;
+
+    @Data
+    public static class Project {
+        private String id;
+        private String PjId;
+        private String name;
+        private String groupCode;
+    }
+
+    @Data
+    public static class Client {
+        private String protocol;
+        private String target_ip;
+        private Integer target_port;
+        private Integer max_size;
+        private Integer sleepcount;
+
+        private String separate_begin;
+        private String separate_end;
+        private Boolean compress;
+        private Boolean transparent;
+        private Boolean usecurrentdate;
+        private Boolean server_is_iot_collect;
+        private Boolean server_is_iot_control;
+        private String buildingheart_sign;
+    }
+
+}

+ 119 - 0
src/main/java/com/persagy/iottransfer/config/KafkaCommonConfig.java

@@ -0,0 +1,119 @@
+package com.persagy.iottransfer.config;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.kafka.KafkaProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
+import org.springframework.kafka.core.DefaultKafkaProducerFactory;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.listener.ContainerProperties;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * kafka配置,实际上,在KafkaAutoConfiguration中已经有默认的根据配置文件信息创建配置,但是自动配置属性没有涵盖所有
+ * 我们可以自定义创建相关bean,进行如下配置
+ *
+ * @author zhoujy
+ * @date 20181217
+ **/
+@Configuration
+@EnableConfigurationProperties({KafkaProperties.class})
+@ConditionalOnProperty(prefix = "spring.kafka", name = "enable", havingValue = "true")
+public class KafkaCommonConfig implements InitializingBean {
+
+    private final KafkaProperties properties;
+    @Value("${spring.kafka.consumer.topics}")
+    private String topics;
+
+    public KafkaCommonConfig(KafkaProperties properties) {
+        this.properties = properties;
+    }
+
+    //构造消费者属性map,ConsumerConfig中的可配置属性比spring boot自动配置要多
+    private Map<String, Object> consumerProperties() {
+//        props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
+        return properties.buildConsumerProperties();
+    }
+
+    /**
+     * 不使用spring boot默认方式创建的DefaultKafkaConsumerFactory,重新定义创建方式
+     *
+     * @return
+     */
+    @Bean("consumerFactory")
+    public DefaultKafkaConsumerFactory consumerFactory() {
+        return new DefaultKafkaConsumerFactory(consumerProperties());
+    }
+
+
+    @Bean("listenerContainerFactory")
+    //个性化定义消费者
+    public ConcurrentKafkaListenerContainerFactory listenerContainerFactory(DefaultKafkaConsumerFactory consumerFactory) {
+        //指定使用DefaultKafkaConsumerFactory
+        ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory();
+        factory.setConsumerFactory(consumerFactory);
+
+        //设置消费者ack模式为手动,看需求设置
+        factory.getContainerProperties().setAckMode(ContainerProperties.AckMode.MANUAL_IMMEDIATE);
+        //设置可批量拉取消息消费,拉取数量一次3,看需求设置
+        factory.setConcurrency(1);
+        factory.setBatchListener(true);
+        return factory;
+    }
+
+   /* @Bean
+     //代码创建方式topic
+    public NewTopic batchTopic() {
+        return new NewTopic("topic.quick.batch", 8, (short) 1);
+    }*/
+
+    //创建生产者配置map,ProducerConfig中的可配置属性比spring boot自动配置要多
+    private Map<String, Object> producerProperties() {
+        return properties.buildProducerProperties();
+    }
+
+    /**
+     * 不使用spring boot的KafkaAutoConfiguration默认方式创建的DefaultKafkaProducerFactory,重新定义
+     *
+     * @return
+     */
+    @Bean("produceFactory")
+    public DefaultKafkaProducerFactory produceFactory() {
+        return new DefaultKafkaProducerFactory(producerProperties());
+    }
+
+
+    /**
+     * 不使用spring boot的KafkaAutoConfiguration默认方式创建的KafkaTemplate,重新定义
+     *
+     * @param produceFactory
+     * @return
+     */
+    @Bean
+    public KafkaTemplate kafkaTemplate(DefaultKafkaProducerFactory produceFactory) {
+        return new KafkaTemplate(produceFactory);
+    }
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        String topicName = wireTopics();
+        System.setProperty("topicName", topicName);
+        System.out.println("### set system config topic:{}" + topicName);
+    }
+
+    private String wireTopics() {
+        Set<String> topicSet = new HashSet<>();
+        topicSet.add(topics);
+        return StringUtils.join(topicSet, ",");
+    }
+
+}

+ 37 - 0
src/main/java/com/persagy/iottransfer/config/ProjectClent.java

@@ -0,0 +1,37 @@
+package com.persagy.iottransfer.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @description:iot-project address and projectid map
+ * @author:lgy
+ * @data:2021/8/27 14:48
+ */
+@Service
+public class ProjectClent {
+    @Autowired
+    IotProperties iotProperties;
+
+    public final Map<String,String> addressProjectMap = new ConcurrentHashMap<>();
+
+    public  String getProject(String address){
+        return addressProjectMap.get(address);
+    }
+
+    public  String getProject(String address,String message){
+        if(addressProjectMap.containsKey(address)){
+            return addressProjectMap.get(address);
+        }
+        for (IotProperties.Project project : iotProperties.projects) {
+            if(message.contains(project.getId())){
+                addressProjectMap.put(address,project.getId());
+            }
+        }
+        return addressProjectMap.get(address);
+    }
+
+}

+ 39 - 0
src/main/java/com/persagy/iottransfer/init/DaemonThread.java

@@ -0,0 +1,39 @@
+package com.persagy.iottransfer.init;
+
+import cn.hutool.core.thread.ThreadUtil;
+import com.persagy.iottransfer.client.IotClient;
+import com.persagy.iottransfer.client.IotClientReceiveMessageThread;
+import com.persagy.iottransfer.config.ProjectClent;
+import com.persagy.iottransfer.kafka.KafkaProducer;
+import com.persagy.iottransfer.server.IotServer;
+import com.persagy.iottransfer.server.IotServerReceiveMessageThread;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+
+@WebListener
+@Slf4j
+public class DaemonThread implements ServletContextListener {
+
+    @Autowired
+    KafkaProducer kafkaProducer;
+
+    @Autowired
+    IotServer iotServer;
+    @Autowired
+    IotClient iotClient;
+    @Autowired
+    ProjectClent projectClent;
+    @Override
+    public void contextInitialized(ServletContextEvent sce) {
+        iotServer.init();
+        iotClient.init();
+        //异步消费消息
+        ThreadUtil.execAsync(new IotServerReceiveMessageThread(kafkaProducer,projectClent), true);
+        ThreadUtil.execAsync(new IotClientReceiveMessageThread(kafkaProducer), true);
+        log.info("----------contextInitialize end--------------");
+    }
+}

+ 351 - 0
src/main/java/com/persagy/iottransfer/init/alibabaiotgateway.java

@@ -0,0 +1,351 @@
+package com.persagy.iottransfer.init;
+
+import io.netty.handler.proxy.HttpProxyHandler;
+import io.netty.handler.proxy.ProxyHandler;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.qpid.jms.JmsConnection;
+import org.apache.qpid.jms.JmsConnectionExtensions;
+import org.apache.qpid.jms.JmsConnectionFactory;
+import org.apache.qpid.jms.JmsConnectionListener;
+import org.apache.qpid.jms.message.JmsInboundMessageDispatch;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.core.annotation.Order;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.stereotype.Component;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.jms.*;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+/**
+ * @description:模拟连接阿里iot
+ * @author:lgy
+ * @data:2021/8/28 17:39
+ */
+@Component
+@Order(value = 1)
+@EnableAsync
+@ConditionalOnProperty(prefix = "spring", name="location", havingValue="Cloud")
+public class alibabaiotgateway implements ApplicationRunner {
+    private final static Logger logger = LoggerFactory.getLogger(alibabaiotgateway.class);
+    @Value("${alibaba.iot.accessKey}")
+    private  String accessKey ;
+    @Value("${alibaba.iot.accessSecret}")
+    private  String accessSecret ;
+    @Value("${alibaba.iot.consumerGroupId}")
+    private  String consumerGroupId ;
+
+    //iotInstanceId:企业版实例请填写实例ID,公共实例请填空字符串""。
+    @Value("${alibaba.iot.iotInstanceId}")
+    private  String iotInstanceId ;
+
+    //控制台服务端订阅中消费组状态页客户端ID一栏将显示clientId参数。
+    //建议使用机器UUID、MAC地址、IP等唯一标识等作为clientId。便于您区分识别不同的客户端。
+    @Value("${alibaba.iot.clientId}")
+    private  String clientId ;
+
+    //${YourHost}为接入域名,请参见AMQP客户端接入说明文档。
+    @Value("${alibaba.iot.host}")
+    private  String host ;
+    @Value("${alibaba.iot.proxy}")
+    private  boolean proxy;
+    @Value("${alibaba.iot.proxyhost}")
+    private  String proxyhost;
+    @Value("${alibaba.iot.proxyport}")
+    private  Integer proxyport;
+
+
+
+    // 指定单个进程启动的连接数
+    // 单个连接消费速率有限,请参考使用限制,最大64个连接
+    // 连接数和消费速率及rebalance相关,建议每500QPS增加一个连接
+    private static int connectionCount = 4;
+
+    //业务处理异步线程池,线程池参数可以根据您的业务特点调整,或者您也可以用其他异步方式处理接收到的消息。
+    private final static ExecutorService executorService = new ThreadPoolExecutor(
+            Runtime.getRuntime().availableProcessors(),
+            Runtime.getRuntime().availableProcessors() * 2, 60, TimeUnit.SECONDS,
+            new LinkedBlockingQueue(50000));
+
+
+//    public static void main(String[] args) throws Exception {
+//        List<Connection> connections = new ArrayList<>();
+//
+//        //参数说明,请参见AMQP客户端接入说明文档。
+//        for (int i = 0; i < connectionCount; i++) {
+//            long timeStamp = System.currentTimeMillis();
+//            //签名方法:支持hmacmd5、hmacsha1和hmacsha256。
+//            String signMethod = "hmacsha1";
+//
+//            //userName组装方法,请参见AMQP客户端接入说明文档。
+//            String userName = clientId +"-" + i + "|authMode=aksign"
+//                    + ",signMethod=" + signMethod
+//                    + ",timestamp=" + timeStamp
+//                    + ",authId=" + accessKey
+//                    + ",iotInstanceId=" + iotInstanceId
+//                    + ",consumerGroupId=" + consumerGroupId
+//                    + "|";
+//            //计算签名,password组装方法,请参见AMQP客户端接入说明文档。
+//            String signContent = "authId=" + accessKey + "&timestamp=" + timeStamp;
+//            String password = doSign(signContent, accessSecret, signMethod);
+//            //amqp.idleTimeout
+//            String connectionUrl = "failover:(amqps://" + host + ":5671?amqp.idleTimeout=80000)"
+//                    + "?failover.reconnectDelay=30";
+//
+//            Hashtable<String, String> hashtable = new Hashtable<>();
+//            hashtable.put("connectionfactory.SBCF", connectionUrl);
+//            hashtable.put("queue.QUEUE", "default");
+//            hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
+//            Context context = new InitialContext(hashtable);
+//            ConnectionFactory cf = (ConnectionFactory)context.lookup("SBCF");
+//            Destination queue = (Destination)context.lookup("QUEUE");
+//            // 创建连接。
+//            Connection connection = cf.createConnection(userName, password);
+//            connections.add(connection);
+//
+//            ((JmsConnection)connection).addConnectionListener(myJmsConnectionListener);
+//            // 创建会话。
+//            // Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()。
+//            // Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)。
+//            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+//
+//            connection.start();
+//            // 创建Receiver连接。
+//            MessageConsumer consumer = session.createConsumer(queue);
+//            consumer.setMessageListener(messageListener);
+//        }
+//
+//        logger.info("amqp demo is started successfully, and will exit after 60s ");
+//
+//        // 结束程序运行
+//        Thread.sleep(60 * 1000);
+//        logger.info("run shutdown");
+//
+//        connections.forEach(c-> {
+//            try {
+//                c.close();
+//            } catch (JMSException e) {
+//                logger.error("failed to close connection", e);
+//            }
+//        });
+//
+//        executorService.shutdown();
+//        if (executorService.awaitTermination(10, TimeUnit.SECONDS)) {
+//            logger.info("shutdown success");
+//        } else {
+//            logger.info("failed to handle messages");
+//        }
+//    }
+
+    private static MessageListener messageListener = new MessageListener() {
+        @Override
+        public void onMessage(final Message message) {
+            try {
+                //1.收到消息之后一定要ACK。
+                // 推荐做法:创建Session选择Session.AUTO_ACKNOWLEDGE,这里会自动ACK。
+                // 其他做法:创建Session选择Session.CLIENT_ACKNOWLEDGE,这里一定要调message.acknowledge()来ACK。
+                // message.acknowledge();
+                //2.建议异步处理收到的消息,确保onMessage函数里没有耗时逻辑。
+                // 如果业务处理耗时过程过长阻塞住线程,可能会影响SDK收到消息后的正常回调。
+                executorService.submit(new Runnable() {
+                    @Override
+                    public void run() {
+                        processMessage(message);
+                    }
+                });
+            } catch (Exception e) {
+                logger.error("submit task occurs exception ", e);
+            }
+        }
+    };
+
+    /**
+     * 在这里处理您收到消息后的具体业务逻辑。
+     */
+    private static void processMessage(Message message) {
+        try {
+            byte[] body = message.getBody(byte[].class);
+            String content = new String(body);
+            String topic = message.getStringProperty("topic");
+            String messageId = message.getStringProperty("messageId");
+            logger.info("receive message"
+                    + ",\n topic = " + topic
+                    + ",\n messageId = " + messageId
+                    + ",\n content = " + content);
+        } catch (Exception e) {
+            logger.error("processMessage occurs error ", e);
+        }
+    }
+
+    private static JmsConnectionListener myJmsConnectionListener = new JmsConnectionListener() {
+        /**
+         * 连接成功建立。
+         */
+        @Override
+        public void onConnectionEstablished(URI remoteURI) {
+            logger.info("onConnectionEstablished, remoteUri:{}", remoteURI);
+        }
+
+        /**
+         * 尝试过最大重试次数之后,最终连接失败。
+         */
+        @Override
+        public void onConnectionFailure(Throwable error) {
+            logger.error("onConnectionFailure, {}", error.getMessage());
+        }
+
+        /**
+         * 连接中断。
+         */
+        @Override
+        public void onConnectionInterrupted(URI remoteURI) {
+            logger.info("onConnectionInterrupted, remoteUri:{}", remoteURI);
+        }
+
+        /**
+         * 连接中断后又自动重连上。
+         */
+        @Override
+        public void onConnectionRestored(URI remoteURI) {
+            logger.info("onConnectionRestored, remoteUri:{}", remoteURI);
+        }
+
+        @Override
+        public void onInboundMessage(JmsInboundMessageDispatch envelope) {}
+
+        @Override
+        public void onSessionClosed(Session session, Throwable cause) {}
+
+        @Override
+        public void onConsumerClosed(MessageConsumer consumer, Throwable cause) {}
+
+        @Override
+        public void onProducerClosed(MessageProducer producer, Throwable cause) {}
+    };
+
+    /**
+     * 计算签名,password组装方法,请参见AMQP客户端接入说明文档。
+     */
+    private static String doSign(String toSignString, String secret, String signMethod) throws Exception {
+        SecretKeySpec signingKey = new SecretKeySpec(secret.getBytes(), signMethod);
+        Mac mac = Mac.getInstance(signMethod);
+        mac.init(signingKey);
+        byte[] rawHmac = mac.doFinal(toSignString.getBytes());
+        return Base64.encodeBase64String(rawHmac);
+    }
+
+    @Async
+    @Override
+    public void run(ApplicationArguments args) throws Exception {
+        List<Connection> connections = new ArrayList<>();
+
+        //参数说明,请参见AMQP客户端接入说明文档。
+        for (int i = 0; i < connectionCount; i++) {
+            long timeStamp = System.currentTimeMillis();
+            //签名方法:支持hmacmd5、hmacsha1和hmacsha256。
+            String signMethod = "hmacsha1";
+
+            //userName组装方法,请参见AMQP客户端接入说明文档。
+            String userName = clientId +"-" + i + "|authMode=aksign"
+                    + ",signMethod=" + signMethod
+                    + ",timestamp=" + timeStamp
+                    + ",authId=" + accessKey
+                    + ",iotInstanceId=" + iotInstanceId
+                    + ",consumerGroupId=" + consumerGroupId
+                    + "|";
+            //计算签名,password组装方法,请参见AMQP客户端接入说明文档。
+            String signContent = "authId=" + accessKey + "&timestamp=" + timeStamp;
+            String password = doSign(signContent, accessSecret, signMethod);
+            //amqp.idleTimeout
+            String connectionUrl = "failover:(amqps://" + host + ":5671?amqp.idleTimeout=80000)"
+                    + "?failover.reconnectDelay=30";
+
+            Hashtable<String, String> hashtable = new Hashtable<>();
+            hashtable.put("connectionfactory.SBCF", connectionUrl);
+            hashtable.put("queue.QUEUE", "default");
+            hashtable.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jms.jndi.JmsInitialContextFactory");
+            Context context = new InitialContext(hashtable);
+
+            Connection connection = null;
+            if (proxy){
+                logger.info(">>>>进入代理服务处理方法");
+                //   context =new InitialContext(hashtable);
+//                JMSConnectionFactory cf1 = (JMSConnectionFactory) context.lookup("SBCF");
+//                Supplier<ProxyHandler> proxyHandlerSupplier =()->{
+//                  return new HttpProxyHandler(new InetSocketAddress(proxyhost,proxyport)) ;
+//                };
+//                cf1.setExtension(JmsConnectionExtensions.PROXY_HANDLER_SUPPLIER.toString(),(connection1,remote)->{
+//                    return proxyHandlerSupplier;
+//                });
+                Supplier<ProxyHandler> proxyHandlerSupplier =()-> new HttpProxyHandler(new InetSocketAddress(proxyhost,proxyport));
+                JmsConnectionFactory factory = (JmsConnectionFactory) context.lookup("SBCF");
+                factory.setExtension(JmsConnectionExtensions.PROXY_HANDLER_SUPPLIER.toString(), (connection1, remote) -> {
+//                    SocketAddress proxyAddress = new InetSocketAddress(proxyhost, proxyport);
+//                    Supplier<ProxyHandler> proxyHandlerFactory = () -> {
+//                        return new HttpProxyHandler(proxyAddress);
+//                    };
+                    return proxyHandlerSupplier;
+                });
+                connection = factory.createConnection(userName, password);
+                logger.info(">>>>>>>创建阿里iot通过招商代理访问互联网");
+            }else{
+                ConnectionFactory cf = (ConnectionFactory)context.lookup("SBCF");
+                // 创建连接。
+                connection= cf.createConnection(userName, password);
+            }
+
+            Destination queue = (Destination)context.lookup("QUEUE");
+            connections.add(connection);
+
+            ((JmsConnection)connection).addConnectionListener(myJmsConnectionListener);
+            // 创建会话。
+            // Session.CLIENT_ACKNOWLEDGE: 收到消息后,需要手动调用message.acknowledge()。
+            // Session.AUTO_ACKNOWLEDGE: SDK自动ACK(推荐)。
+            // Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
+            connection.start();
+
+            // 创建Receiver连接。
+            MessageConsumer consumer = session.createConsumer(queue);
+            consumer.setMessageListener(messageListener);
+        }
+
+        logger.info("amqp demo is started successfully, and will exit after 60s ");
+
+        // 结束程序运行
+        Thread.sleep(60 * 1000);
+        logger.info("run shutdown");
+
+        connections.forEach(c-> {
+            try {
+                c.close();
+            } catch (JMSException e) {
+                logger.error("failed to close connection", e);
+            }
+        });
+        executorService.shutdown();
+        if (executorService.awaitTermination(10, TimeUnit.SECONDS)) {
+            logger.info("shutdown success");
+        } else {
+            logger.info("failed to handle messages");
+        }
+    }
+}

+ 54 - 0
src/main/java/com/persagy/iottransfer/kafka/KafkaConsumerCloud2Edge.java

@@ -0,0 +1,54 @@
+package com.persagy.iottransfer.kafka;
+
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.iottransfer.client.IotClient;
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.util.IClientManager;
+import com.persagy.iottransfer.server.IotServer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.kafka.support.Acknowledgment;
+import org.springframework.kafka.support.KafkaHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/20 10:10
+ */
+@Component
+@Slf4j
+@ConditionalOnProperty(prefix = "iot.type",name = "edge",havingValue = "true",matchIfMissing = false)
+public class KafkaConsumerCloud2Edge {
+
+    @KafkaListener(topics = KafkaProducer.TOPIC_COLLECT2EDGE, groupId = KafkaProducer.TOPIC_EDGE)
+    public void topicCollect2Edge(ConsumerRecord<String, String> record, Acknowledgment ack, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
+        Optional<String> message = Optional.ofNullable(record.value());
+        if (message.isPresent()) {
+            PacketEntity packetEntity = JSONObject.parseObject(message.get(), PacketEntity.class);
+            String projectId = packetEntity.getProjectId();
+            Packet packet = packetEntity.getContent();
+            IotServer.tcpCollectServerManager.AppendToSendByProject(projectId,packet);
+            log.info("topicCollect2Edge 消费了: Topic:" + topic + ",Message:" + packetEntity);
+            ack.acknowledge();
+        }
+    }
+    @KafkaListener(topics = KafkaProducer.TOPIC_CONTROL2EDGE, groupId = KafkaProducer.TOPIC_EDGE)
+    public void topicControl2Edge(ConsumerRecord<String, String> record, Acknowledgment ack, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
+        Optional<String> message = Optional.ofNullable(record.value());
+        if (message.isPresent()) {
+            PacketEntity packetEntity = JSONObject.parseObject(message.get(), PacketEntity.class);
+            String projectId = packetEntity.getProjectId();
+            Packet packet = packetEntity.getContent();
+            IotServer.tcpControlServerManager.AppendToSendByProject(projectId,packet);
+            log.info("topicControl2Edge 消费了: Topic:" + topic + ",Message:" + packetEntity);
+            ack.acknowledge();
+        }
+    }
+}

+ 68 - 0
src/main/java/com/persagy/iottransfer/kafka/KafkaConsumerEdge2Cloud.java

@@ -0,0 +1,68 @@
+package com.persagy.iottransfer.kafka;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.iottransfer.client.IotClient;
+import com.persagy.iottransfer.communication.entity.Packet;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.communication.util.IClientManager;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.kafka.clients.consumer.ConsumerRecord;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.kafka.support.Acknowledgment;
+import org.springframework.kafka.support.KafkaHeaders;
+import org.springframework.messaging.handler.annotation.Header;
+import org.springframework.stereotype.Component;
+
+import java.util.Optional;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/20 10:10
+ */
+@Component
+@Slf4j
+@ConditionalOnProperty(prefix = "iot.type",name = "cloud",havingValue = "true",matchIfMissing = false)
+public class KafkaConsumerEdge2Cloud {
+
+
+    @KafkaListener(topics = KafkaProducer.TOPIC_EDGE2COLLECT, groupId = KafkaProducer.TOPIC_CLOUD)
+    public void topicEdge2Collect(ConsumerRecord<String, String> record, Acknowledgment ack, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
+        Optional<String> message = Optional.ofNullable(record.value());
+        try {
+            if (message.isPresent()) {
+                String msg = message.get();
+                log.info("topic iot.edge2collect------消费了: Topic:" + topic + ",Message:" + msg);
+                PacketEntity packetEntity = JSONObject.parseObject(msg, PacketEntity.class);
+                IClientManager clientManager = IotClient.clientproject2CollectManagerMap.get(packetEntity.getProjectId());
+                clientManager.AppendToSend(packetEntity.content);
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(),e);
+        }
+        ack.acknowledge();
+    }
+
+    @KafkaListener(topics = KafkaProducer.TOPIC_EDGE2CONTROL, groupId = KafkaProducer.TOPIC_CLOUD)
+    public void topicEdge2Control(ConsumerRecord<String, String> record, Acknowledgment ack, @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) {
+        Optional<String> message = Optional.ofNullable(record.value());
+        try {
+            if (message.isPresent()) {
+                String msg = message.get();
+                log.info("topic iot.edge2control------消费了: Topic:" + topic + ",Message:" + msg);
+                PacketEntity packetEntity = JSONObject.parseObject(msg, PacketEntity.class);
+                IClientManager clientManager = IotClient.clientproject2ControlManagerMap.get(packetEntity.getProjectId());
+                if(clientManager != null){
+                    clientManager.AppendToSend(packetEntity.content);
+                }
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(),e);
+        }
+        ack.acknowledge();
+    }
+
+
+}

+ 73 - 0
src/main/java/com/persagy/iottransfer/kafka/KafkaProducer.java

@@ -0,0 +1,73 @@
+package com.persagy.iottransfer.kafka;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.support.SendResult;
+import org.springframework.stereotype.Component;
+import org.springframework.util.concurrent.ListenableFuture;
+import org.springframework.util.concurrent.ListenableFutureCallback;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/20 10:11
+ */
+@Component
+@Slf4j
+public class KafkaProducer {
+
+    //自定义topic
+    public static final String TOPIC_EDGE2COLLECT = "iot.edge2collect";
+    public static final String TOPIC_EDGE2CONTROL = "iot.edge2control";
+    public static final String TOPIC_COLLECT2EDGE = "iot.collect2edge";
+    public static final String TOPIC_CONTROL2EDGE = "iot.control2edge";
+    //group
+    public static final String TOPIC_EDGE = "topic.edge";
+    public static final String TOPIC_CLOUD = "topic.cloud";
+    @Autowired
+    private KafkaTemplate<String, Object> kafkaTemplate;
+
+    public void sendMessage(PacketEntity obj, String topic) {
+        String obj2String = JSONObject.toJSONString(obj);
+        log.info("准备发送消息为:{}", obj2String);
+        if(StrUtil.isEmpty(obj.getProjectId())){
+            //log.info("项目id为空,丢去:{}", obj2String);
+            return;
+        }
+        //发送消息
+        ListenableFuture<SendResult<String, Object>> future = kafkaTemplate.send(topic, obj2String);
+        future.addCallback(new ListenableFutureCallback<SendResult<String, Object>>() {
+            @Override
+            public void onFailure(Throwable throwable) {
+                //发送失败的处理
+                log.info(topic + " - 生产者 发送消息失败:" + throwable.getMessage());
+            }
+
+            @Override
+            public void onSuccess(SendResult<String, Object> stringObjectSendResult) {
+                //成功的处理
+                log.info(topic + " - 生产者 发送消息成功:" + stringObjectSendResult.toString());
+            }
+        });
+    }
+
+    public void sendFromedge2collect(PacketEntity obj) {
+        sendMessage(obj, TOPIC_EDGE2COLLECT);
+    }
+
+    public void sendFromedge2control(PacketEntity obj) {
+        sendMessage(obj, TOPIC_EDGE2CONTROL);
+    }
+
+    public void sendFromcollect2edge(PacketEntity obj) {
+        sendMessage(obj, TOPIC_COLLECT2EDGE);
+    }
+
+    public void sendFromcontrol2edge(PacketEntity obj) {
+        sendMessage(obj, TOPIC_CONTROL2EDGE);
+    }
+}

+ 43 - 0
src/main/java/com/persagy/iottransfer/kafka/KafkaServerMessageReceiver.java

@@ -0,0 +1,43 @@
+//package com.persagy.iottransfer.kafka;
+//
+//
+//import lombok.extern.slf4j.Slf4j;
+//import org.apache.kafka.clients.consumer.ConsumerRecord;
+//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.kafka.annotation.KafkaListener;
+//import org.springframework.kafka.support.Acknowledgment;
+//
+//import java.util.Iterator;
+//import java.util.List;
+//
+//@Configuration
+//@ConditionalOnProperty(prefix = "spring.kafka",name = "enable",havingValue = "true")
+//@Slf4j
+//public class KafkaServerMessageReceiver {
+//
+//
+//    /**
+//     * listenerContainerFactory设置了批量拉取消息,因此参数是List<ConsumerRecord<Integer, String>>,否则是ConsumerRecord
+//     * @param integerStringConsumerRecords
+//     * @param acknowledgment
+//     */
+//    @KafkaListener(topics = {"#{'${topicName}'.split(',')}"}, containerFactory = "listenerContainerFactory")
+//    public void registryReceiver(List<ConsumerRecord<Integer, String>> integerStringConsumerRecords, Acknowledgment acknowledgment) {
+//        Iterator<ConsumerRecord<Integer, String>> it = integerStringConsumerRecords.iterator();
+//        while (it.hasNext()){
+//            ConsumerRecord<Integer, String> consumerRecords = it.next();
+//            String topic = consumerRecords.topic();
+//            //转换数据
+//            try {
+//
+//            }catch (Exception e){
+//
+//            }
+//
+//        }
+//        acknowledgment.acknowledge();
+//    }
+//
+//
+//}

+ 57 - 0
src/main/java/com/persagy/iottransfer/server/IotServer.java

@@ -0,0 +1,57 @@
+package com.persagy.iottransfer.server;
+
+import com.persagy.iottransfer.communication.mina.tcp.server.TCPServerManager;
+import com.persagy.iottransfer.communication.mina.udp.server.UDPServerManager;
+import com.persagy.iottransfer.config.CollectServerProperties;
+import com.persagy.iottransfer.config.ControlServerProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @description:
+ * @author:lgy
+ * @data:2021/8/26 15:18
+ */
+@Service
+public class IotServer {
+    public static TCPServerManager tcpCollectServerManager = TCPServerManager.builder().build();
+    public static TCPServerManager tcpControlServerManager = TCPServerManager.builder().build();
+
+    @Autowired
+    CollectServerProperties collectServerProperties;
+    @Autowired
+    ControlServerProperties controlServerProperties;
+
+    public void init() {
+
+        if (collectServerProperties.getTcp_enable()) {
+            tcpCollectServerManager = new TCPServerManager(collectServerProperties.getTcp_bind_ip(), collectServerProperties.getTcp_bind_port(), "utf-8", collectServerProperties.getCompress(), collectServerProperties.getMax_size(), (byte) collectServerProperties.getSeparate_begin().charAt(0),
+                    (byte) collectServerProperties.getSeparate_end().charAt(0));
+            tcpCollectServerManager.hasRemark(100);
+            tcpCollectServerManager.Start();
+        }
+
+        if (controlServerProperties.getTcp_enable()) {
+            tcpControlServerManager = new TCPServerManager(controlServerProperties.getTcp_bind_ip(), controlServerProperties.getTcp_bind_port(), "utf-8", controlServerProperties.getCompress(), controlServerProperties.getMax_size(), (byte) controlServerProperties.getSeparate_begin().charAt(0),
+                    (byte) controlServerProperties.getSeparate_end().charAt(0));
+            tcpControlServerManager.hasRemark(100);
+            tcpControlServerManager.Start();
+
+        }
+
+//    public static  UDPServerManager udpCollectServerManager = UDPServerManager.builder().build();
+//    public static  UDPServerManager udpControlServerManager = UDPServerManager.builder().build();
+//        if (collectServerProperties.getUdp_enable()) {
+//            udpCollectServerManager = new UDPServerManager(collectServerProperties.getUdp_bind_ip(), collectServerProperties.getUdp_bind_port(), "utf-8", collectServerProperties.getCompress(), collectServerProperties.getMax_size());
+//            udpCollectServerManager.hasRemark(100);
+//            udpCollectServerManager.Start();
+//        }
+//        if (controlServerProperties.getUdp_enable()) {
+//            udpControlServerManager = new UDPServerManager(controlServerProperties.getUdp_bind_ip(), controlServerProperties.getUdp_bind_port(), "utf-8", controlServerProperties.getCompress(), controlServerProperties.getMax_size());
+//            udpControlServerManager.hasRemark(100);
+//            udpControlServerManager.Start();
+//        }
+    }
+
+
+}

+ 75 - 0
src/main/java/com/persagy/iottransfer/server/IotServerReceiveMessageThread.java

@@ -0,0 +1,75 @@
+package com.persagy.iottransfer.server;
+
+import cn.hutool.core.thread.ThreadUtil;
+import com.persagy.iottransfer.communication.entity.PacketEntity;
+import com.persagy.iottransfer.config.ProjectClent;
+import com.persagy.iottransfer.kafka.KafkaProducer;
+import com.persagy.iottransfer.server.IotServer;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @description: AlarmMessage消费线程
+ * @author:LuoGuangyi
+ * @company:PersagyTechnologyCo.,Ltd
+ * @since:2021/01/29 17:08
+ * @version:V1.0
+ **/
+@Slf4j
+public class IotServerReceiveMessageThread implements Runnable {
+
+    KafkaProducer kafkaProducer;
+    ProjectClent projectClent;
+
+    PacketEntity tcpControl = null;
+    PacketEntity tcpCollect = null;
+    public IotServerReceiveMessageThread(KafkaProducer kafkaProducer,ProjectClent projectClent) {
+        this.kafkaProducer = kafkaProducer;
+        this.projectClent = projectClent;
+    }
+
+    @Override
+    public void run() {
+        ThreadUtil.execAsync(()->{
+            while (true){
+                try {
+                    tcpControl = IotServer.tcpControlServerManager.takeRece();
+                    if (tcpControl != null) {
+                        if (tcpControl.address == null) {
+                            break;
+                        }
+                        addProject(tcpControl,"tcpControl");
+                        log.info("收到iot-project 控制消息:{}", tcpControl);
+                        kafkaProducer.sendFromedge2control(tcpControl);
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage(),e);
+                }
+            }
+        },true);
+        ThreadUtil.execAsync(()->{
+            while (true){
+                try {
+                    tcpCollect = IotServer.tcpCollectServerManager.takeRece();
+                    if (tcpCollect != null) {
+                        if (tcpCollect.address == null) {
+                            break;
+                        }
+                        addProject(tcpCollect,"tcpCollect");
+                        log.info("收到iot-project 采集消息:{}", tcpCollect);
+                        kafkaProducer.sendFromedge2collect(tcpCollect);
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage(),e);
+                }
+            }
+        },true);
+        log.info("----------contextInitialize end--------------");
+    }
+
+    //添加项目id
+    private void addProject(PacketEntity packetEntity,String type){
+        String address = packetEntity.address;
+        packetEntity.setProjectId(projectClent.getProject(address,packetEntity.getContent().packetString));
+        packetEntity.setType(type);
+    }
+}

+ 1 - 0
src/main/resources/application.properties

@@ -0,0 +1 @@
+

+ 122 - 0
src/main/resources/application.yml

@@ -0,0 +1,122 @@
+server:
+  #需要更改
+  port: 8880
+spring:
+  # 应用名称
+  application:
+    name: iot-transfer
+  kafka:
+    enable: true
+    bootstrap-servers: 192.168.64.16:9092
+    producer:
+      # 发生错误后,消息重发的次数。
+      retries: 2
+      #当有多个消息需要被发送到同一个分区时,生产者会把它们放在同一个批次里。该参数指定了一个批次可以使用的内存大小,按照字节数计算。
+      batch-size: 65536
+      # 设置生产者内存缓冲区的大小。
+      buffer-memory: 33554432
+      # 键的序列化方式
+      key-serializer: org.apache.kafka.common.serialization.StringSerializer
+      # 值的序列化方式
+      value-serializer: org.apache.kafka.common.serialization.StringSerializer
+      # acks=0 : 生产者在成功写入消息之前不会等待任何来自服务器的响应。
+      # acks=1 : 只要集群的首领节点收到消息,生产者就会收到一个来自服务器成功响应。
+      # acks=all :只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应。
+      acks: 1
+      properties:
+        max.request.size: 50000000
+    consumer:
+      topics:
+      # 自动提交的时间间隔 在spring boot 2.X 版本中这里采用的是值的类型为Duration 需要符合特定的格式,如1S,1M,2H,5D
+      auto-commit-interval: 1S
+      # 该属性指定了消费者在读取一个没有偏移量的分区或者偏移量无效的情况下该作何处理:
+      # latest(默认值)在偏移量无效的情况下,消费者将从最新的记录开始读取数据(在消费者启动之后生成的记录)
+      # earliest :在偏移量无效的情况下,消费者将从起始位置读取分区的记录
+      auto-offset-reset: earliest
+      # 是否自动提交偏移量,默认值是true,为了避免出现重复数据和数据丢失,可以把它设置为false,然后手动提交偏移量
+      enable-auto-commit: false
+      fetch-min-size: 10
+      fetch-max-wait: 500
+      # 键的反序列化方式
+      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
+      # 值的反序列化方式
+      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
+      properties:
+        max.partition.fetch.bytes: 50000000
+    listener:
+      # 在侦听器容器中运行的线程数。
+      concurrency: 5
+      #listner负责ack,每调用一次,就立即commit
+      ack-mode: manual_immediate
+      missing-topics-fatal: false
+iot:
+  type:
+    cloud: false
+    edge: false
+  server:
+    collect:
+      tcp_enable: true
+      tcp_bind_ip: 0.0.0.0
+      tcp_bind_port: 8851
+      udp_enable: true
+      udp_bind_ip: 0.0.0.0
+      udp_bind_port: 8851
+      max_size: 1000
+      sleepcount: 1000
+      separate_begin: (
+      separate_end: )
+      compress: false
+    control:
+      tcp_enable: true
+      tcp_bind_ip: 0.0.0.0
+      tcp_bind_port: 8855
+      udp_enable: true
+      udp_bind_ip: 0.0.0.0
+      udp_bind_port: 8855
+      max_size: 1000
+      sleepcount: 1000
+      separate_begin: (
+      separate_end: )
+      compress: false
+  clients:
+    - protocol: TCP
+      target_ip: 127.0.0.1
+      target_port: 8861
+      max_size: 1000
+      sleepcount: 1000
+      separate_begin: (
+      separate_end: )
+      compress: false
+      transparent: false
+      usecurrentdate: false
+      server_is_iot_collect: true
+      server_is_iot_control: false
+    - protocol: TCP
+      target_ip: 127.0.0.1
+      target_port: 8862
+      max_size: 1000
+      sleepcount: 1000
+      separate_begin: (
+      separate_end: )
+      compress: false
+      transparent: false
+      usecurrentdate: false
+      server_is_iot_collect: false
+      server_is_iot_control: true
+  projects:
+    - id: 4403050019
+      PjId: Pj4403050019
+      name: 深圳太子广场汇港二期
+      groupCode: ZS
+    - id: 3201130004
+      PjId: Pj3201130004
+      name: 南京招商燕子矶花园城
+      groupCode: ZS
+    - id: 5101080004
+      PjId: Pj5101080004
+      name: 成都招商花园城
+      groupCode: ZS
+    - id: 3101150007
+      PjId: Pj3101150007
+      name: 上海森兰花园城
+      groupCode: ZS

+ 20 - 0
src/main/resources/log4j.properties

@@ -0,0 +1,20 @@
+log4j.rootLogger=INFO,ConsoleAppender,RollingLogFileAppender
+#print file   org.apache.log4j.DailyRollingFileAppender
+log4j.appender.RollingLogFileAppender=org.apache.log4j.RollingFileAppender
+log4j.appender.RollingLogFileAppender.Threshold=INFO
+log4j.appender.RollingLogFileAppender.ImmediateFlush=false
+log4j.appender.RollingLogFileAppender.File=../logs/iot-transfer/transferlog.log
+log4j.appender.RollingLogFileAppender.Append=true
+log4j.appender.RollingLogFileAppender.MaxFileSize=20MB
+log4j.appender.RollingLogFileAppender.Encoding=UTF-8
+log4j.appender.RollingLogFileAppender.MaxBackupIndex=100
+log4j.appender.RollingLogFileAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.RollingLogFileAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss}:%-5p %l - %m%n
+#print Console
+log4j.appender.ConsoleAppender=org.apache.log4j.ConsoleAppender
+log4j.appender.ConsoleAppender.Threshold=INFO
+log4j.appender.ConsoleAppender.ImmediateFlush=true
+log4j.appender.ConsoleAppender.Target=System.out
+log4j.appender.ConsoleAppender.layout=org.apache.log4j.PatternLayout
+log4j.appender.ConsoleAppender.Encoding=UTF-8
+log4j.appender.ConsoleAppender.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} %m%n

+ 95 - 0
src/main/resources/logback-spring.xml

@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--scan:  当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。
+scanPeriod:  设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。
+debug:  当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。
+configuration 子节点为 appender、logger、root       -->
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
+    <!--用于区分不同应用程序的记录-->
+    <contextName>iot-project</contextName>
+    <!--日志文件所在目录,如果是tomcat,如下写法日志文件会在则为${TOMCAT_HOME}/bin/logs/目录下-->
+    <property name="LOG_HOME" value="../logs/iot-transfer"/>
+    <!--
+    %p:输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
+    %r:输出自应用启动到输出该日志讯息所耗费的毫秒数
+    %t:输出产生该日志事件的线程名
+    %f:输出日志讯息所属的类别的类别名
+    %c:输出日志讯息所属的类的全名
+    %d:输出日志时间点的日期或时间,指定格式的方式: %d{yyyy-MM-dd HH:mm:ss}
+    %l:输出日志事件的发生位置,即输出日志讯息的语句在他所在类别的第几行。
+    %m:输出代码中指定的讯息,如log(message)中的message
+    %n:输出一个换行符号
+-->
+    <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符-->
+    <property name="pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS}  %-5level [%thread] %logger{36}  %msg%n"/>
+
+    <!--控制台-->
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <!-- 字符串System.out(默认)或者System.err -->
+        <target>System.out</target>
+        <!-- 对记录事件进行格式化 -->
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <pattern>${pattern}</pattern>
+            <!--解决乱码问题-->
+            <charset>UTF-8</charset>
+        </encoder>
+    </appender>
+    <!--滚动文件-->
+    <appender name="infoFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 被写入的文件名,可以是相对目录,也可以是绝对目录,如果上级目录不存在会自动创建 -->
+        <file>${LOG_HOME}/log.log</file>
+        <!-- ThresholdFilter:临界值过滤器,过滤掉 TRACE 和 DEBUG 级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--查看   gunzip -c xx.log.gz | less-->
+            <fileNamePattern>${LOG_HOME}/log.%d{yyyy-MM-dd}.log.%i.gz</fileNamePattern>
+            <totalSizeCap>300MB</totalSizeCap>
+            <maxHistory>5</maxHistory><!--保存最近30天的日志-->
+        </rollingPolicy>
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>${pattern}</pattern>
+        </encoder>
+    </appender>
+    <!--滚动文件-->
+    <appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- ThresholdFilter:临界值过滤器,过滤掉 TRACE 和 DEBUG 级别的日志 -->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>error</level>
+        </filter>
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>100MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log.%i.gz</fileNamePattern>
+            <maxHistory>30</maxHistory><!--保存最近30天的日志-->
+            <totalSizeCap>2GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <encoder>
+            <charset>UTF-8</charset>
+            <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] %-5level %logger{36} : %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <!--将日志输出到logstack-->
+    <!--<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
+        <destination>47.93.173.81:7002</destination>
+        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
+            <charset>UTF-8</charset>
+        </encoder>
+        <keepAliveDuration>5 minutes</keepAliveDuration>
+    </appender>-->
+
+    <!--这里如果是info,spring、mybatis等框架则不会输出:TRACE < DEBUG < INFO <  WARN < ERROR-->
+    <!--root是所有logger的祖先,均继承root,如果某一个自定义的logger没有指定level,就会寻找
+    父logger看有没有指定级别,直到找到root。-->
+    <root level="INFO">
+        <appender-ref ref="stdout"/>
+        <appender-ref ref="infoFile"/>
+    </root>
+</configuration>

+ 13 - 0
src/test/java/com/persagy/iottransfer/IotTransferApplicationTests.java

@@ -0,0 +1,13 @@
+package com.persagy.iottransfer;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class IotTransferApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}