diff --git a/mirai-core/pom.xml b/mirai-core/pom.xml
index 6d5c6ff3d..3a43788e1 100644
--- a/mirai-core/pom.xml
+++ b/mirai-core/pom.xml
@@ -21,21 +21,10 @@
     </parent>
 
     <dependencies>
+        <!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
         <dependency>
-            <groupId>org.apache.mina</groupId>
-            <artifactId>mina-core</artifactId>
-        </dependency>
-        <!-- https://mvnrepository.com/artifact/org.apache.mina/mina-filter-ssl -->
-        <dependency>
-            <groupId>org.apache.mina</groupId>
-            <artifactId>mina-filter-ssl</artifactId>
-            <version>1.1.7</version>
-        </dependency>
-        <!-- https://mvnrepository.com/artifact/org.apache.mina/mina-filter-compression -->
-        <dependency>
-            <groupId>org.apache.mina</groupId>
-            <artifactId>mina-filter-compression</artifactId>
-            <version>2.1.3</version>
+            <groupId>org.jetbrains.kotlinx</groupId>
+            <artifactId>kotlinx-coroutines-core</artifactId>
         </dependency>
 
         <dependency>
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
index 0d51307a0..0c15c2c9a 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/contact/QQ.kt
@@ -22,4 +22,12 @@ class QQ(number: Int) : Contact(number) {
     fun at(): String {
         return "[@$number]"
     }
+
+
+    /*
+    Make that we can use (QQ + QQ2 + QQ3).sendMessage( )
+
+    operator fun plus(qq: QQ): QQCombination {
+
+    }*/
 }
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/MemoryMonitorTest.java b/mirai-core/src/main/java/net/mamoe/mirai/network/MemoryMonitorTest.java
deleted file mode 100644
index 2660ed08a..000000000
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/MemoryMonitorTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package net.mamoe.mirai.network;
-
-import org.apache.mina.core.buffer.IoBuffer;
-import org.apache.mina.core.service.IoHandlerAdapter;
-import org.apache.mina.core.session.IdleStatus;
-import org.apache.mina.core.session.IoSession;
-import org.apache.mina.filter.executor.ExecutorFilter;
-import org.apache.mina.filter.logging.LoggingFilter;
-import org.apache.mina.transport.socket.DatagramSessionConfig;
-import org.apache.mina.transport.socket.nio.NioDatagramAcceptor;
-
-import java.io.IOException;
-import java.net.*;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-public class MemoryMonitorTest {
-
-    private static final long serialVersionUID = 1L;
-
-    public static final int PORT = 8080;
-
-    public MemoryMonitorTest() throws IOException {
-
-        NioDatagramAcceptor acceptor = new NioDatagramAcceptor();//创建一个UDP的接收器
-        acceptor.setHandler(new YourHandler());//设置接收器的处理程序
-
-        Executor threadPool = Executors.newFixedThreadPool(1500);//建立线程池
-        acceptor.getFilterChain().addLast("exector", new ExecutorFilter(threadPool));
-        acceptor.getFilterChain().addLast("logger", new LoggingFilter());
-
-        DatagramSessionConfig dcfg = acceptor.getSessionConfig();//建立连接的配置文件
-        dcfg.setReadBufferSize(4096);//设置接收最大字节默认2048
-        dcfg.setReceiveBufferSize(1024);//设置输入缓冲区的大小
-        dcfg.setSendBufferSize(1024);//设置输出缓冲区的大小
-        dcfg.setReuseAddress(true);//设置每一个非主监听连接的端口可以重用
-
-        acceptor.bind(new InetSocketAddress(PORT));//绑定端口
-    }
-
-
-    public static void main(String[] args) throws IOException {
-        new MemoryMonitorTest();
-    }
-
-    public class YourHandler extends IoHandlerAdapter {
-
-//messageSent是Server响应给Clinet成功后触发的事件
-
-        @Override
-        public void messageSent(IoSession session, Object message) throws Exception {
-            if (message instanceof IoBuffer) {
-                IoBuffer buffer = (IoBuffer) message;
-                byte[] bb = buffer.array();
-                for (int i = 0; i < bb.length; i++) {
-                    System.out.print((char) bb[i]);
-                }
-            }
-        }
-
-//抛出异常触发的事件
-
-        @Override
-        public void exceptionCaught(IoSession session, Throwable cause)
-                throws Exception {
-            cause.printStackTrace();
-            session.close(true);
-        }
-
-//Server接收到UDP请求触发的事件
-
-        @Override
-        public void messageReceived(IoSession session, Object message)
-                throws Exception {
-            System.out.println("messageReceived");
-            if (message instanceof IoBuffer) {
-                IoBuffer buffer = (IoBuffer) message;
-//            byte[] bb = buffer.array();
-//            for(int i=0;i<bb.length;i++) {
-//            System.out.print((char)bb[i]);
-//            }
-                IoBuffer buffer1 = IoBuffer.wrap("11".getBytes());//返回信息给Clinet端
-                session.write(buffer1);
-
-//声明这里message必须为IoBuffer类型
-            }
-
-        }
-
-//连接关闭触发的事件
-
-        @Override
-        public void sessionClosed(IoSession session) throws Exception {
-            System.out.println("Session closed...");
-        }
-
-//建立连接触发的事件
-
-        @Override
-        public void sessionCreated(IoSession session) throws Exception {
-            System.out.println("Session created...");
-            SocketAddress remoteAddress = session.getRemoteAddress();
-            System.out.println(remoteAddress);
-
-        }
-
-//会话空闲
-
-        @Override
-        public void sessionIdle(IoSession session, IdleStatus status)
-                throws Exception {
-            System.out.println("Session idle...");
-        }
-
-//打开连接触发的事件,它与sessionCreated的区别在于,一个连接地址(A)第一次请求Server会建立一个Session默认超时时间为1分钟,此时若未达到超时时间这个连接地址(A)再一次向Server发送请求即是sessionOpened(连接地址(A)第一次向Server发送请求或者连接超时后向Server发送请求时会同时触发sessionCreated和sessionOpened两个事件)
-
-        @Override
-        public void sessionOpened(IoSession session) throws Exception {
-            System.out.println("Session Opened...");
-            SocketAddress remoteAddress = session.getRemoteAddress();
-            System.out.println(remoteAddress);
-        }
-
-
-        public void send(String host, int port) {
-
-            try {
-                InetAddress ia = InetAddress.getByName(host);
-                DatagramSocket socket = new DatagramSocket(9999);
-                socket.connect(ia, port);
-                byte[] buffer = new byte[1024];
-
-                buffer = ("22")
-                        .getBytes();
-                DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
-                System.out.println(dp.getLength());
-                DatagramPacket dp1 = new DatagramPacket(new byte[22312], 22312);
-                socket.send(dp);
-                socket.receive(dp1);
-                byte[] bb = dp1.getData();
-                for (int i = 0; i < dp1.getLength(); i++) {
-                    System.out.print((char) bb[i]);
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-        }
-    }
-}
-
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
index a5a247cf5..9fadb75d5 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/Robot.kt
@@ -1,6 +1,8 @@
 package net.mamoe.mirai.network
 
 import io.netty.channel.Channel
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
 import net.mamoe.mirai.network.packet.client.ClientPacket
 import net.mamoe.mirai.network.packet.client.login.*
 import net.mamoe.mirai.network.packet.client.writeHex
@@ -129,18 +131,16 @@ class Robot(val number: Int, private val password: String) {
             e.printStackTrace()
         }
         packet.writeHex(Protocol.tail)
-        println(packet)
-        println(packet.toByteArray().toUByteArray().toHexString())
         /*val p = DatagramPacket(packet.toByteArray());
         p.socketAddress = this.serverAddress*/
         //ctx.writeAndFlush(packet.toByteArray()).sync()
-        send(packet.toByteArray())
+        MiraiLogger info "Sending: $packet"
+        GlobalScope.launch {
+            send(packet.toByteArray())
+        }
         //println(channel!!.writeAndFlush(packet.toByteArray()).channel().connect(serverAddress).sync().get())
-        MiraiLogger info "Packet sent: $packet"
     }
 
-    private fun DatagramPacket(toByteArray: ByteArray): DatagramPacket = DatagramPacket(toByteArray, toByteArray.size, this.serverAddress)
-
     //  private val socket = DatagramSocket(15314)
 
     @ExperimentalUnsignedTypes
@@ -151,6 +151,7 @@ class Robot(val number: Int, private val password: String) {
 
             val dp1 = DatagramPacket(ByteArray(22312), 22312)
             socket.send(DatagramPacket(data, data.size))
+            MiraiLogger info "Packet sent: ${data.toUByteArray().toHexString()}"
             socket.receive(dp1)
             val zeroByte: Byte = 0
             var i = dp1.data.size - 1;
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt
index 207d974dd..8de5f1272 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/ClientPacket.kt
@@ -41,7 +41,7 @@ abstract class ClientPacket : ByteArrayDataOutputStream(), Packet {
      * Encode this packet.
      *
      *
-     * Before sending the packet, an [tail][Protocol.tail] will be added.
+     * Before sending the packet, a [tail][Protocol.tail] will be added.
      */
     @Throws(IOException::class)
     abstract fun encode()
@@ -99,6 +99,22 @@ fun DataOutputStream.writeVarInt(dec: UInt) {
     throw UnsupportedOperationException()
 }
 
+fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, key: ByteArray) {
+    this.write(TEACryptor.encrypt(byteArray, key))
+}
+
+fun DataOutputStream.encryptAndWrite(byteArray: ByteArray, cryptor: TEACryptor) {
+    this.write(cryptor.encrypt(byteArray))
+}
+
+fun DataOutputStream.encryptAndWrite(key: ByteArray, encoder: DataOutputStream.() -> Unit) {
+    this.write(TEACryptor.encrypt(ByteArrayDataOutputStream().let { it.encoder(); it.toByteArray() }, key))
+}
+
+fun DataOutputStream.encryptAndWrite(cryptor: TEACryptor, encoder: DataOutputStream.() -> Unit) {
+    this.write(cryptor.encrypt(ByteArrayDataOutputStream().let { it.encoder(); it.toByteArray() }))
+}
+
 @ExperimentalUnsignedTypes
 @Throws(IOException::class)
 fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray) {
@@ -112,7 +128,7 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log
         val md5_1 = md5(password);
         val md5_2 = md5(md5_1 + "00 00 00 00".hexToBytes() + qq.toByteArray())
         it.write(md5_1)
-        it.writeInt(loginTime)//todo FIXED 12(maybe 11???) bytes??? check that
+        it.writeInt(loginTime)
         it.writeByte(0);
         it.writeZero(4 * 3)
         it.writeIP(loginIP)
@@ -124,27 +140,44 @@ fun DataOutputStream.writeTLV0006(qq: Int, password: String, loginTime: Int, log
 }
 
 @ExperimentalUnsignedTypes
-fun DataOutputStream.writeCRC32() {
-    getRandomKey(16).let {
+fun DataOutputStream.writeCRC32() = writeCRC32(getRandomKey(16))
+
+
+@ExperimentalUnsignedTypes
+fun DataOutputStream.writeCRC32(key: ByteArray) {
+    key.let {
         write(it)//key
-        writeLong(getCrc32(it))//todo may be int? check that.
+        writeInt(getCrc32(it))
     }
 }
 
-fun DataOutputStream.writeHostname() {
-    val hostName: String = InetAddress.getLocalHost().hostName.let { it.substring(0, it.length - 3) };
-    this.writeShort(hostName.length / 2);//todo check that
-    this.writeShort(hostName.length);
-    this.writeBytes(hostName)//todo 这个对吗?
+fun DataOutputStream.writeDeviceName() {
+    val deviceName = InetAddress.getLocalHost().hostName
+    this.writeShort(deviceName.length + 2)
+    this.writeShort(deviceName.length)
+    this.writeBytes(deviceName)
 }
 
-fun Int.toByteArray(): ByteArray = byteArrayOf(//todo 检查这方法对不对, 这其实就是从 DataInputStream copy来的
+/**
+ * 255 -> 00 00 00 FF
+ */
+fun Int.toByteArray(): ByteArray = byteArrayOf(
         (this.ushr(24) and 0xFF).toByte(),
         (this.ushr(16) and 0xFF).toByte(),
         (this.ushr(8) and 0xFF).toByte(),
         (this.ushr(0) and 0xFF).toByte()
 )
 
+/**
+ * 255 -> FF 00 00 00
+ */
+fun Int.toLByteArray(): ByteArray = byteArrayOf(
+        (this.ushr(0) and 0xFF).toByte(),
+        (this.ushr(8) and 0xFF).toByte(),
+        (this.ushr(16) and 0xFF).toByte(),
+        (this.ushr(24) and 0xFF).toByte()
+)
+
 @ExperimentalUnsignedTypes
 fun Int.toHexString(separator: String = " "): String = this.toByteArray().toUByteArray().toHexString(separator);
 
@@ -155,14 +188,14 @@ private fun md5(byteArray: ByteArray): ByteArray = MessageDigest.getInstance("MD
 @ExperimentalUnsignedTypes
 @Throws(IOException::class)
 fun DataOutputStream.writeZero(count: Int) {
-    for (x in 0..count) {
+    repeat(count) {
         this.writeByte(0)
     }
 }
 
 @Throws(IOException::class)
 fun DataOutputStream.writeRandom(length: Int) {
-    for (i in 0 until length) {
+    repeat(length) {
         this.writeByte((Math.random() * 255).toInt().toByte().toInt())
     }
 }
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
index e6628739e..7a4354c82 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/client/login/ClientLoginPacket.kt
@@ -7,6 +7,7 @@ import net.mamoe.mirai.util.ByteArrayDataOutputStream
 import net.mamoe.mirai.util.TEACryptor
 import net.mamoe.mirai.util.getRandomKey
 import net.mamoe.mirai.util.hexToBytes
+import java.net.InetAddress
 
 /**
  * Password submission (0836_622)
@@ -15,7 +16,14 @@ import net.mamoe.mirai.util.hexToBytes
  */
 @PacketId("08 36 31 03")
 @ExperimentalUnsignedTypes
-class ClientPasswordSubmissionPacket(private val qq: Int, private val password: String, private val loginTime: Int, private val loginIP: String, private val tgtgtKey: ByteArray, private val token0825: ByteArray) : ClientPacket() {
+class ClientPasswordSubmissionPacket(
+        private val qq: Int,
+        private val password: String,
+        private val loginTime: Int,
+        private val loginIP: String,
+        private val tgtgtKey: ByteArray,
+        private val token0825: ByteArray
+) : ClientPacket() {
     @ExperimentalUnsignedTypes
     override fun encode() {
         this.writeQQ(qq)
@@ -24,13 +32,10 @@ class ClientPasswordSubmissionPacket(private val qq: Int, private val password:
         this.writeHex("00 00 00 10")
         this.writeHex(Protocol._0836key1)
 
-        this.write(TEACryptor.encrypt(object : ByteArrayDataOutputStream() {
-            override fun toByteArray(): ByteArray {
-                writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825)
-                writePart2()
-                return super.toByteArray()
-            }
-        }.toByteArray(), Protocol.shareKey.hexToBytes()))
+        this.encryptAndWrite(Protocol.shareKey.hexToBytes()) {
+            writePart1(qq, password, loginTime, loginIP, tgtgtKey, token0825)
+            writePart2()
+        }
     }
 }
 
@@ -68,6 +73,10 @@ open class ClientLoginResendPacket internal constructor(val qq: Int, val passwor
     }
 }
 
+fun main() {
+    println(InetAddress.getLocalHost().hostAddress)
+}
+
 @ExperimentalUnsignedTypes
 @PacketId("08 28 04 34")
 class ClientLoginSucceedConfirmationPacket(
@@ -112,7 +121,7 @@ class ClientLoginSucceedConfirmationPacket(
                 this.writeHex("68")
 
                 this.writeHex("00 00 00 00 00 2D 00 06 00 01")
-                this.writeIP(loginIP)//本地IP地址? todo test that
+                this.writeIP(InetAddress.getLocalHost().hostName)//? todo 这随便扔的
 
                 return super.toByteArray()
             }
@@ -126,12 +135,12 @@ class ClientLoginSucceedConfirmationPacket(
 @ExperimentalUnsignedTypes
 private fun ClientPacket.writePart1(qq: Int, password: String, loginTime: Int, loginIP: String, tgtgtKey: ByteArray, token0825: ByteArray) {
 
-    this.writeQQ(System.currentTimeMillis().toInt())//that's correct
+    this.writeInt(System.currentTimeMillis().toInt())
     this.writeHex("01 12")//tag
     this.writeHex("00 38")//length
     this.write(token0825)//length
     this.writeHex("03 0F")//tag
-    this.writeHostname()//todo 务必检查这个
+    this.writeDeviceName()
     /*易语言源码: PCName就是HostName
     PCName = BytesToStr (Ansi转Utf8 (取主机名 ()))
     PCName = 取文本左边 (PCName, 取文本长度 (PCName) - 3)*/
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
index 6f7321687..f695112e4 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/ServerPacket.kt
@@ -56,6 +56,10 @@ abstract class ServerPacket(val input: DataInputStream) : Packet {
             }
         }
     }
+
+    override fun toString(): String {
+        return this.javaClass.simpleName + this.javaClass.declaredFields.joinToString(", ", "{", "}") { it.trySetAccessible(); it.name + "=" + it.get(this) }
+    }
 }
 
 
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/touch/ServerTouchResponsePacket.kt b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/touch/ServerTouchResponsePacket.kt
index 1f4ca760e..ea78ab557 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/touch/ServerTouchResponsePacket.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/network/packet/server/touch/ServerTouchResponsePacket.kt
@@ -1,6 +1,5 @@
 package net.mamoe.mirai.network.packet.server.touch
 
-import lombok.ToString
 import net.mamoe.mirai.network.Protocol
 import net.mamoe.mirai.network.packet.server.ServerPacket
 import net.mamoe.mirai.network.packet.server.readIP
@@ -18,7 +17,6 @@ import java.io.DataInputStream
  *
  * @author Him188moe
  */
-@ToString
 class ServerTouchResponsePacket(inputStream: DataInputStream) : ServerPacket(inputStream) {
     var serverIP: String? = null;
 
diff --git a/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt b/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt
index b9f5d07be..aab755144 100644
--- a/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt
+++ b/mirai-core/src/main/java/net/mamoe/mirai/util/Utils.kt
@@ -28,28 +28,37 @@ object Utils {
     }
 }
 
+fun ByteArray.toHexString(): String = toHexString(" ")
 fun ByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator)
+
 @ExperimentalUnsignedTypes
 fun UByteArray.toHexString(separator: String = " "): String = Utils.toHexString(this, separator)
 
 @ExperimentalUnsignedTypes
-fun Byte.toHexString(): String = this.toUByte().toString(16)
+fun UByteArray.toHexString(): String = toHexString(" ")
 
+@ExperimentalUnsignedTypes
+fun Byte.toHexString(): String = this.toUByte().toString(16)
 
 @ExperimentalUnsignedTypes
 fun String.hexToBytes(): ByteArray = Protocol.hexToBytes(this)
 @ExperimentalUnsignedTypes
 fun String.hexToUBytes(): UByteArray = Protocol.hexToUBytes(this)
 
-@ExperimentalUnsignedTypes//todo test that
+@ExperimentalUnsignedTypes
 fun String.hexToShort(): Short = hexToBytes().let { ((it[1].toInt() shl 8) + it[0]).toShort() }
 
+@ExperimentalUnsignedTypes
+fun String.hexToByte(): Byte = hexToBytes()[0]
+
 open class ByteArrayDataOutputStream : DataOutputStream(ByteArrayOutputStream()) {
     open fun toByteArray(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
     @ExperimentalUnsignedTypes
     open fun toUByteArray(): UByteArray = (out as ByteArrayOutputStream).toByteArray().toUByteArray();
 }
 
+fun lazyEncode(t: ByteArrayDataOutputStream.() -> Unit): ByteArray = ByteArrayDataOutputStream().let { it.t(); return it.toByteArray() }
+
 @ExperimentalUnsignedTypes
 fun getRandomKey(length: Int): ByteArray {
     val bytes = LinkedList<Byte>();
@@ -57,4 +66,4 @@ fun getRandomKey(length: Int): ByteArray {
     return bytes.toByteArray();
 }
 
-fun getCrc32(key: ByteArray): Long = with(CRC32()) { update(key); return@with this.value };
\ No newline at end of file
+fun getCrc32(key: ByteArray): Int = CRC32().let { it.update(key); it.value.toInt() }
\ No newline at end of file
diff --git a/mirai-core/src/test/java/HaxComparator.java b/mirai-core/src/test/java/HaxComparator.java
index 89d534322..685e95746 100644
--- a/mirai-core/src/test/java/HaxComparator.java
+++ b/mirai-core/src/test/java/HaxComparator.java
@@ -13,11 +13,13 @@ public class HaxComparator {
 
     private static String GREEN = "\033[33m";
 
+    private static String UNKNOWN = "\033[30m";
+
     public static String compare(String hax1s, String hax2s){
         StringBuilder builder = new StringBuilder();
 
-        String[] hax1 = hax1s.trim().split(" ");
-        String[] hax2 = hax2s.trim().split(" ");
+        String[] hax1 = hax1s.trim().replace("\n", "").split(" ");
+        String[] hax2 = hax2s.trim().replace("\n", "").split(" ");
 
         if(hax1.length == hax2.length){
             builder.append(GREEN).append("长度一致:").append(hax1.length);
@@ -25,6 +27,8 @@ public class HaxComparator {
             builder.append(RED).append("长度不一致").append(hax1.length).append("/").append(hax2.length);
         }
 
+
+        StringBuilder numberLine = new StringBuilder();
         StringBuilder hax1b = new StringBuilder();
         StringBuilder hax2b = new StringBuilder();
         int dif = 0;
@@ -61,18 +65,37 @@ public class HaxComparator {
                 }
             }
 
-            hax1b.append(h1).append(" ");
-            hax2b.append(h2).append(" ");
+            numberLine.append(UNKNOWN).append(getNumber(i)).append(" ");
+            hax1b.append(h1).append("  ");
+            hax2b.append(h2).append("  ");
             if(isDif){
                 ++dif;
             }
         }
 
-        return (builder.append(" ").append(dif).append(" 个不同").append("\n").append(hax1b).append("\n").append(hax2b)).toString();
+        return (builder.append(" ").append(dif).append(" 个不同").append("\n")
+                .append(numberLine).append("\n")
+                .append(hax1b).append("\n")
+                .append(hax2b))
+                .toString();
+    }
+
+    private static String getNumber(int number) {
+        if (number < 10) {
+            return "00" + number;
+        }
+        if (number < 100) {
+            return "0" + number;
+        }
+        return String.valueOf(number);
     }
 
 
     public static void main(String[] args){
-        System.out.println(HaxComparator.compare("00 01 09 00 70 00 01 23 7B FE 83 D1 37 64 46 84 9D E9 9C E7 BB 8E 44 00 38 9B A4 3B C2 BB 49 4C DA B0 A5 5C C8 27 29 74 EF CB 38 59 4E 03 C8 15 C6 F9 BF 3F 88 22 7E 22 5B 48 02 71 59 1A 2C C8 42 BA 81 76 66 0C 46 91 89 6C B2 17 BF 2A 00 F8 8B 00 20 7C 28 07 3D AA 24 EF B4 49 9D 85 7F 4C F5 41 56 F4 1F AD 53 81 9F C1 03 F3 03 65 DD 0C 04 CC 68 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6","AA CC AA DD EE GG HH"));
+        System.out.println(HaxComparator.compare(
+                "02 37 13 08 28 31 03 76 E4 B8 DD 03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19 02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3 00 00 00 10 EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA B4 4E C2 36 01 12 00 38 A9 76 88 3D C3 26 28 32 77 D1 EA 55 23 52 12 A5 75 1F EB F9 3B 6D 36 50 5E CF 8E 16 16 19 10 6B 83 FA 6F 0E D6 8E ED A4 BF BC 6C DE 34 61 D9 BB 96 16 C5 CE FE 76 27 22 03 0F 00 11 00 0F 44 45 53 4B 54 4F 50 2D 4D 31 37 4A 52 45 55 00 05 00 06 00 02 76 E4 B8 DD 00 06 00 78 9F DE A7 F7 6D 6C B3 D6 91 47 B8 3D 97 EB 79 ED 82 A6 9C 77 1E FC 74 C6 0C 31 99 DA 97 21 CD 90 00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B 00 1A 00 40 2D FB 2B 26 88 BE 00 43 A9 25 00 06 5A DD D3 1F 7D 95 9C A3 50 25 C4 65 F8 C6 0E 09 A0 00 30 57 26 13 7F 5A C6 01 F8 F6 63 4C 67 13 B3 B1 0F 30 89 60 81 B8 1A CD D5 02 FB 26 45 A5 27 79 34 D0 00 18 00 16 00 01 00 00 04 53 00 00 00 01 00 00 15 85 76 E4 B8 DD 00 00 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6 03 12 00 05 01 00 00 00 01 05 08 00 05 10 00 00 00 00 03 13 00 19 01 01 02 00 10 04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA 00 00 00 00 01 02 00 62 00 01 04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48 00 38 E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3 00 14 54 30 26 84 06 E4 97 E3 63 37 C5 8C 34 72 2D C3 6B 74 83 4C 57 17 EF 65 F7 66 94 6B 2A A4 7F E9 72 11 3B 33 0A 03\n"
+                ,
+                "02 37 13 08 36 31 03 76 E4 B8 DD 03 00 00 00 01 01 01 00 00 68 20 00 00 00 00 00 01 01 03 00 19 02 6D 28 41 D2 A5 6F D2 FC 3E 2A 1F 03 75 DE 6E 28 8F A8 19 3E 5F 16 49 D3 00 00 00 10 EF 4A 36 6A 16 A8 E6 3D 2E EA BD 1F 98 C1 3C DA B4 15 18 27 01 12 00 38 C3 D9 67 C5 43 ED E4 FF 64 B7 68 80 19 4E AA 17 C2 77 C0 51 82 E0 E1 35 1C E5 B6 50 49 AE 16 51 F3 59 B4 B2 00 E8 ED AD 99 6D 09 2C D6 0F 73 09 D6 44 DE 74 58 C5 24 B2 03 0F 00 11 00 0F 44 45 53 4B 54 4F 50 2D 4D 31 37 4A 52 45 55 00 05 00 06 00 02 76 E4 B8 DD 00 06 00 78 D8 20 30 26 EB 91 D2 66 ED A2 73 A1 1F BA C0 BD C6 5C F0 35 83 CB 24 0B FE 62 5F C0 1F 74 6D F0 00 15 00 30 00 01 01 27 9B C7 F5 00 10 65 03 FD 8B 00 00 00 00 00 00 00 00 00 00 00 00 02 90 49 55 33 00 10 15 74 C4 89 85 7A 19 F5 5E A9 C9 A3 5E 8A 5A 9B 00 1A 00 40 B1 AC 22 BA AE F3 4F 8F A9 16 BB 14 BA 10 00 BA 47 87 E3 5F A0 C6 1F 14 F5 34 AC E2 5C 9E 2F C6 F7 04 52 E1 9D FC 5C BE A4 7F 38 D8 D8 C4 08 51 D6 9E 37 16 8E 24 DF A2 5B 5D DB AB 2E 00 76 EE 00 18 00 16 00 01 00 00 04 53 00 00 00 01 00 00 15 85 76 E4 B8 DD 00 00 00 00 00 01 03 00 14 00 01 00 10 60 C9 5D A7 45 70 04 7F 21 7D 84 50 5C 66 A5 C6 03 12 00 05 01 00 00 00 01 05 08 00 05 10 00 00 00 00 03 13 00 19 01 01 02 00 10 04 EA 78 D1 A4 FF CD CC 7C B8 D4 12 7D BB 03 AA 00 00 00 00 00 01 02 00 62 00 01 04 EB B7 C1 86 F9 08 96 ED 56 84 AB 50 85 2E 48 00 38 E9 AA 2B 4D 26 4C 76 18 FE 59 D5 A9 82 6A 0C 04 B4 49 50 D7 9B B1 FE 5D 97 54 8D 82 F3 22 C2 48 B9 C9 22 69 CA 78 AD 3E 2D E9 C9 DF A8 9E 7D 8C 8D 6B DF 4C D7 34 D0 D3 00 14 5F C9 F5 37 A0 11 D7 E6 26 37 A3 2B E3 21 11 83 F0 65 32 06 6A BC 59 C4 20 9F 84 E8 C9 FE 8F 3B 6D 96 12 F2 A4 03\n"
+        ));
     }
 }
diff --git a/pom.xml b/pom.xml
index 7926b018b..28d665c86 100644
--- a/pom.xml
+++ b/pom.xml
@@ -63,12 +63,6 @@
     </build>
 
     <dependencies>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.12</version>
-            <scope>test</scope>
-        </dependency>
 
         <dependency>
             <groupId>com.intellij</groupId>
@@ -94,13 +88,6 @@
 
     <dependencyManagement>
         <dependencies>
-            <!-- https://mvnrepository.com/artifact/org.apache.mina/mina-core -->
-            <dependency>
-                <groupId>org.apache.mina</groupId>
-                <artifactId>mina-core</artifactId>
-                <version>2.1.3</version>
-            </dependency>
-
             <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
             <dependency>
                 <groupId>net.java.dev.jna</groupId>
@@ -114,6 +101,13 @@
                 <version>2.8.5</version>
             </dependency>
 
+            <!-- https://mvnrepository.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core -->
+            <dependency>
+                <groupId>org.jetbrains.kotlinx</groupId>
+                <artifactId>kotlinx-coroutines-core</artifactId>
+                <version>1.3.0-M2</version>
+            </dependency>
+
             <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
             <dependency>
                 <groupId>io.netty</groupId>