Forráskód Böngészése

改单线程发送消息

wuweihao 5 éve
szülő
commit
fea77fccae

+ 116 - 49
src/main/java/com/fd/controller/DataController.java

@@ -1,8 +1,9 @@
 package com.fd.controller;
 
-import com.fd.entity.Classroom;
-import com.fd.socket.*;
+import com.fd.entity.Room;
+import com.fd.socket.demo.SendMsg;
 import com.fd.util.DataFormatUtils;
+import com.fd.util.FileUtils;
 import com.fd.util.PythonUtils;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Value;
@@ -16,8 +17,8 @@ import org.springframework.web.bind.annotation.RestController;
 import javax.annotation.PostConstruct;
 import java.io.IOException;
 import java.net.Socket;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Created by Owen on 2019/10/22 0022 10:55
@@ -25,7 +26,7 @@ import java.util.List;
 @Log4j2
 @CrossOrigin(maxAge = 3600)
 @RestController
-@RequestMapping("api")
+@RequestMapping("/api")
 public class DataController {
 
     @Value("${python.exePath}")
@@ -51,8 +52,22 @@ public class DataController {
     private Socket client;
 
 
+    // 缓存算法数据
+    private Map<String, List> allmap = new HashMap();
+
+    // 记录调用次数
+    private Integer count = 1;
+
+
+    // 多线程共享变量
+    // false 表示完成
+    private static AtomicBoolean exists = new AtomicBoolean(false);
+
+
+
     /**
      * 初始化
+     *
      * @return
      */
     @PostConstruct
@@ -62,11 +77,6 @@ public class DataController {
         try {
             client = new Socket(ipAddress, port);
             log.info("========= run client ===========");
-
-            // 监听服务端
-            new Thread(new SocketListenThread(client, listenTime)).start();
-//            new Thread(new ReceiveThread(client)).start();
-
         } catch (IOException e) {
             e.printStackTrace();
             log.error(e);
@@ -76,15 +86,13 @@ public class DataController {
     }
 
 
-
     /**
      * 重启socket客户端
      */
-    @GetMapping("restart")
+    @GetMapping("/restart")
     @SuppressWarnings({"rawtypes", "unchecked"})
     private ResponseEntity restartSocketClient() {
         log.info("run restartSocketClient");
-
         try {
             // 判断socket是否关闭连接,如果关闭,重启连接
             boolean closed = client.isClosed();
@@ -104,51 +112,81 @@ public class DataController {
      * 测试联调
      */
 
-    @GetMapping("all")
+    @GetMapping("/all")
     @SuppressWarnings({"rawtypes", "unchecked"})
     private ResponseEntity all() {
         long start = System.currentTimeMillis();
         log.info("run all");
 
-        // 1 通知cpp拍照 #P
-        new Thread(new SendMsgThread(client, "#P")).start();
 
-        // 2 调用算法计算人数
-        List result = PythonUtils.connect(exePath, command);
 
-        // 4 告诉cpp ip+人数
-        new Thread(new SendMsgThread(client, DataFormatUtils.ipFormat(result))).start();
+        // 重启后第一次是没有数据的,模拟一条给他
+        if (allmap.size() == 0) {
+            ArrayList<Object> list = new ArrayList<>();
+            list.add("192.168.0.249:20");
+            allmap.put("result", list);
+        }
+
+        // 从缓存里拿数据
+        List result = allmap.get("result");
 
         // 5 返回结果集给前端
-        result = DataFormatUtils.frontendFormat(result);
+        result = DataFormatUtils.frontendIpFormat2(result);
+
+        if (exists.compareAndSet(false, true)) {
+            // 1 通知cpp拍照 #P
+            SendMsg sendMsg = new SendMsg(client, "#P");
+            sendMsg.send();
+
+            // 调用算法计算人数
+            new Thread(new PythonThread()).start();
+        }
+
 
         long end = System.currentTimeMillis();
-        log.info("Total time: {}s", (end - start) / 1000);
+        log.info("Total count: {} time: {}s", count++, (end - start) / 1000);
         return new ResponseEntity(result, HttpStatus.OK);
     }
 
+    // 调用算法
+    public class PythonThread implements Runnable {
+        @Override
+        public void run() {
+            log.info("run PythonThread");
+            List result = PythonUtils.connect(exePath, command);
+            if (result != null) {
+                allmap.put("result", result);
+            } else {
+                log.info("Python get data is null");
+                 result = allmap.get("result");
+            }
+
+            // 告诉cpp ip+人数
+            SendMsg sendMsg = new SendMsg(client, DataFormatUtils.ipFormat(result));
+            sendMsg.send();
+            // 表示执行完成
+            exists.set(false);
+
+        }
+    }
+
     // ===================================== 测试用 ========================================================
 
 
+
+
     // 返回前端总入口
-    @GetMapping("data")
+    @GetMapping("/data")
     @SuppressWarnings({"rawtypes", "unchecked"})
     private ResponseEntity getData() {
         log.info("run getData");
-//        List connect = PythonUtils.connect(exePath, command);
-        List<Object> list = new ArrayList<>();
-        for (int i = 1; i < 99; i++) {
-            Classroom classroom = new Classroom();
-            classroom.setId(i);
-            classroom.setRegion(DataFormatUtils.randomInt(3, 1));
-            classroom.setStatus(DataFormatUtils.randomInt(2, 0));
-            classroom.setStorey(DataFormatUtils.randomInt(10, 1));
-            classroom.setCount(DataFormatUtils.randomInt(50, 20));
-            list.add(classroom);
-        }
 
+        String[] str = new String[]{"192.168.1.1:10", "192.168.1.2:20", "192.168.2.1:30", "192.168.2.2:40", "192.168.3.1:22"};
+        List<String> strings = Arrays.asList(str);
+
+        List list = DataFormatUtils.frontendIpFormat2(strings);
         try {
-            Thread.sleep(3000);
+            Thread.sleep(1000);
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
@@ -159,7 +197,7 @@ public class DataController {
     /**
      * 测试算法
      */
-    @GetMapping("p")
+    @GetMapping("/python")
     @SuppressWarnings({"rawtypes", "unchecked"})
     private ResponseEntity getDataP() {
         log.info("run testPython");
@@ -167,14 +205,18 @@ public class DataController {
         return new ResponseEntity(connect, HttpStatus.OK);
     }
 
-    // test cpp
-    @GetMapping("6")
+    // 测试 cpp 通信
+    @GetMapping("/cpp")
     @SuppressWarnings({"rawtypes", "unchecked"})
     private ResponseEntity testListen6() {
         log.info("run testListen6");
 
         // 1 通知cpp拍照 #P
-        new Thread(new SendMsgThread(client, "#P")).start();
+//        new Thread(new SendMsgThread(client, "#P")).start();
+
+        // 1 通知cpp拍照 #P
+        SendMsg sendMsg = new SendMsg(client, "#P");
+        sendMsg.send();
 
         List<Object> list = new ArrayList<>();
         for (int i = 0; i < 5; i++) {
@@ -189,8 +231,12 @@ public class DataController {
             e.printStackTrace();
         }
 
-        // 2 告诉cpp ip+人数
-        new Thread(new SendMsgThread(client, DataFormatUtils.ipFormat(list))).start();
+//        // 2 告诉cpp ip+人数
+//        new Thread(new SendMsgThread(client, DataFormatUtils.ipFormat(list))).start();
+
+        // 告诉cpp ip+人数
+        SendMsg sendMsg1 = new SendMsg(client, DataFormatUtils.ipFormat(list));
+        sendMsg1.send();
 
 
         return new ResponseEntity("success", HttpStatus.OK);
@@ -200,7 +246,7 @@ public class DataController {
     /**
      * 循环测试服务器版本
      */
-    @GetMapping("load")
+    @GetMapping("/load")
     @SuppressWarnings({"rawtypes", "unchecked"})
     private void load() {
 
@@ -214,13 +260,18 @@ public class DataController {
                 Thread.sleep(timedTask);
                 long start = System.currentTimeMillis();
 
-                new Thread(new SendMsgThread(client, "#P")).start();
+//                new Thread(new SendMsgThread(client, "#P")).start();
+                // 1 通知cpp拍照 #P
+                SendMsg sendMsg = new SendMsg(client, "#P");
+                sendMsg.send();
 
                 // 2 调用算法计算人数
                 List result = PythonUtils.connect(exePath, command);
 
                 // 3 告诉cpp ip+人数
-                new Thread(new SendMsgThread(client, DataFormatUtils.ipFormat(result))).start();
+//                new Thread(new SendMsgThread(client, DataFormatUtils.ipFormat(result))).start();
+                SendMsg sendMsg1 = new SendMsg(client, DataFormatUtils.ipFormat(result));
+                sendMsg1.send();
 
                 long end = System.currentTimeMillis();
                 log.info("Total count: {} time: {}s", count++, (end - start) / 1000);
@@ -235,9 +286,10 @@ public class DataController {
     /**
      * 循环测试本地版本
      */
-    @GetMapping("1")
+    @GetMapping("/1")
     @SuppressWarnings({"rawtypes", "unchecked"})
     private void load1() {
+        log.info("run load1");
 
         boolean isRunning = true;
 
@@ -245,15 +297,16 @@ public class DataController {
         int count = 1;
         while (isRunning) {
             try {
-                Thread.sleep(timedTask);
+                Thread.sleep(2000);
                 log.info("run timedTask");
                 long start = System.currentTimeMillis();
                 // 1 通知cpp拍照 #P
-                new Thread(new SendMsgThread(client, "#P")).start();
+                SendMsg sendMsg = new SendMsg(client, "#P");
+                sendMsg.send();
 
                 List<Object> list = new ArrayList<>();
                 for (int i = 0; i < 5; i++) {
-                    String ip = "127.0.0." + i;
+                    String ip = "127.0.0.1" + i;
                     String s = ip + ":" + i;
                     list.add(s);
                 }
@@ -261,7 +314,9 @@ public class DataController {
                 Thread.sleep(2000);
 
                 // 2 告诉cpp ip+人数
-                new Thread(new SendMsgThread(client, DataFormatUtils.ipFormat(list))).start();
+                SendMsg sendMsg1 = new SendMsg(client, DataFormatUtils.ipFormat(list));
+                sendMsg1.send();
+
 
                 long end = System.currentTimeMillis();
 
@@ -277,4 +332,16 @@ public class DataController {
     }
 
 
+    @GetMapping("/test")
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private String test2() {
+        log.info("run test2");
+        int i = new Random().nextInt(100);
+        return "success: " + i;
+    }
+
+
+
+
+
 }

+ 20 - 0
src/main/java/com/fd/entity/Room.java

@@ -0,0 +1,20 @@
+package com.fd.entity;
+
+import lombok.Data;
+
+/**
+ * Created by Owen on 2019/10/29 0029 10:30
+ */
+@Data
+public class Room {
+
+//    private Integer id; // 教师id
+
+    private String region; // 区域
+
+//    private Integer storey; // 楼层
+//
+    private Integer status; // 状态:1:异常, 0:正常
+
+    private Integer count; // 人数
+}

+ 76 - 0
src/main/java/com/fd/socket/ReceiveThread.java

@@ -0,0 +1,76 @@
+package com.fd.socket;
+
+
+import lombok.extern.log4j.Log4j2;
+import org.springframework.util.StringUtils;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.Socket;
+
+/**
+ * 多线程封装: 接收端
+ *
+ * 1 接收消息
+ * 2 释放资源
+ * 3 重写run方法
+ */
+@Log4j2
+public class ReceiveThread implements Runnable{
+
+
+
+    private Socket client;
+
+    private boolean isRunning;
+
+    private BufferedReader buf;
+
+    public ReceiveThread(Socket client) {
+        this.client = client;
+        isRunning = true;
+    }
+
+    @Override
+    public void run() {
+        while (isRunning) {
+            try {
+                    buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
+                    String msg = buf.readLine();
+
+                    if (StringUtils.isEmpty(msg)) {
+                        log.error("没有收到服务端消息!");
+                        throw new Exception("没有收到服务端消息!");
+                    }
+
+                    if ("JP".equals(msg)) {
+                        log.info("硬件拍照完成! : {}", msg);
+                    }
+                    if ("JI".equals(msg)) {
+                        log.info("socketServer数据确认成功! : {}", msg);
+                    }
+
+//                    if ("1".equals(msg)) {
+//                        log.info("Listen heartbeat result msg: {}", msg);
+//                    }
+
+//                     关闭接收信息
+//                    isRunning = false;
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                log.error("error ReceiveThread");
+                release();
+            }
+        }
+    }
+
+
+
+    //释放资源
+    private void release(){
+        // 关闭循环
+        this.isRunning = false;
+        CloseUtils.close(buf, client);
+    }
+}

+ 19 - 13
src/main/java/com/fd/socket/SendMsgThread.java

@@ -56,23 +56,29 @@ public class SendMsgThread implements Runnable {
 
             while (isRunning) {
                 try {
-                    buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
-                    String msg = buf.readLine();
+//                    buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
+//                    String msg = buf.readLine();
+//
+//                    if (StringUtils.isEmpty(msg)) {
+//                        log.error("没有收到服务端消息!");
+//                        throw new Exception("没有收到服务端消息!");
+//                    }
+//
+//                    if ("JP".equals(msg)) {
+//                        log.info("硬件拍照完成! : {}", msg);
+//                    }
+//                    if ("JI".equals(msg)) {
+//                        log.info("socketServer数据确认成功! : {}", msg);
+//                    }
+//
+//                    if ("1".equals(msg)) {
+//                        log.info("Listen heartbeat result msg: {}", msg);
+//                    }
 
-                    if (StringUtils.isEmpty(msg)) {
-                        log.error("没有收到服务端消息!");
-                        throw new Exception("没有收到服务端消息!");
-                    }
 
-                    if ("JP".equals(msg)) {
-                        log.info("硬件拍照完成! : {}", msg);
-                    }
-                    if ("JI".equals(msg)) {
-                        log.info("socketServer数据确认成功! : {}", msg);
-                    }
 
 //                     关闭接收信息
-                    isRunning = false;
+//                    isRunning = false;
 
                 } catch (Exception e) {
                     e.printStackTrace();

+ 21 - 13
src/main/java/com/fd/socket/SocketListenThread.java

@@ -50,23 +50,31 @@ public class SocketListenThread implements Runnable {
 
         while (isRunning) {
 
-
+            // 监听频率
             try {
-                // 监听频率
                 Thread.sleep(listenTime);
-                send();
-                buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
-                String msg = buf.readLine();
-                if (StringUtils.isEmpty(msg)) {
-                    log.error("error heartbeat");
-                    throw new Exception("error heartbeat ");
-                }
-                log.info("Listen heartbeat result msg: {}", msg);
-            } catch (IOException | InterruptedException e) {
-                release();
-            } catch (Exception e) {
+            } catch (InterruptedException e) {
                 e.printStackTrace();
             }
+            send();
+
+
+//            try {
+//                // 监听频率
+//                Thread.sleep(listenTime);
+//                send();
+////                buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
+////                String msg = buf.readLine();
+////                if (StringUtils.isEmpty(msg)) {
+////                    log.error("error heartbeat");
+////                    throw new Exception("error heartbeat ");
+////                }
+////                log.info("Listen heartbeat result msg: {}", msg);
+//            } catch (IOException | InterruptedException e) {
+//                release();
+//            } catch (Exception e) {
+//                e.printStackTrace();
+//            }
 
         }
     }

+ 133 - 0
src/main/java/com/fd/socket/demo/SendMsg.java

@@ -0,0 +1,133 @@
+package com.fd.socket.demo;
+
+
+import com.fd.socket.CloseUtils;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.util.StringUtils;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.Socket;
+
+/**
+ * 多线程封装: 发送端
+ *
+ * 1 发送消息
+ * 2 从控制台获取消息
+ * 3 释放资源
+ * 4 重写run方法
+ */
+@Log4j2
+public class SendMsg {
+
+    private Socket client;
+
+    private boolean isRunning;
+
+    private String message;
+
+    // 字节输出流
+    private OutputStream out;
+
+    private BufferedReader buf;
+
+    public SendMsg(Socket client, String message) {
+
+        this.client = client;
+        this.message = message;
+        try {
+             out = client.getOutputStream();
+
+        } catch (IOException e) {
+            log.error("error SendMsgThread");
+            release();
+        }
+    }
+
+
+
+    //发送消息
+    public void send(){
+        String msg = "";
+        try {
+            // 以字节写入
+            out.write(this.message.getBytes());
+            out.flush();
+            log.info("send msg: {}", this.message);
+
+            buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
+            msg = buf.readLine();
+
+            if (StringUtils.isEmpty(msg)) {
+                log.error("没有收到服务端消息!");
+                throw new Exception("没有收到服务端消息!");
+            }
+
+            if ("JP".equals(msg)) {
+                log.info("硬件拍照完成! : {}", msg);
+            } else if ("JI".equals(msg)) {
+                log.info("socketServer数据确认成功! : {}", msg);
+            } else {
+                log.info("Listen heartbeat result msg: {}", msg);
+            }
+
+        } catch (IOException e) {
+            log.error("error SendMsgThread");
+            release();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+    }
+
+    //发送消息
+//    public String send2(){
+//        String msg = "";
+//        try {
+//            // 以字节写入
+//            out.write(this.message.getBytes());
+//            out.flush();
+//            log.info("send msg: {}", this.message);
+//
+//            buf =  new BufferedReader(new InputStreamReader(client.getInputStream()));
+//            msg = buf.readLine();
+//
+//            if (StringUtils.isEmpty(msg)) {
+//                log.error("没有收到服务端消息!");
+//                throw new Exception("没有收到服务端消息!");
+//            }
+//
+//            if ("JP".equals(msg)) {
+//                log.info("硬件拍照完成! : {}", msg);
+//            } else {
+//                log.info("socketServer数据确认成功! : {}", msg);
+//            }
+//
+//        } catch (IOException e) {
+//            log.error("error SendMsgThread");
+//            release();
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//        return msg;
+//    }
+
+
+    //释放资源
+    private void release(){
+        // 关闭循环
+        this.isRunning = false;
+        CloseUtils.close(out, buf, client);
+    }
+
+
+
+
+
+
+
+
+
+}

+ 68 - 5
src/main/java/com/fd/util/DataFormatUtils.java

@@ -1,15 +1,15 @@
 package com.fd.util;
 
 import com.fd.entity.Classroom;
+import com.fd.entity.Room;
+import lombok.extern.log4j.Log4j2;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Random;
+import java.util.*;
 
 /**
  * Created by Owen on 2019/10/23 0023 18:30
  */
+@Log4j2
 public class DataFormatUtils {
 
     // 创建范围随机数
@@ -62,6 +62,68 @@ public class DataFormatUtils {
         return list;
     }
 
+    // 处理返回前端数据ip转换对应教室
+    public static List frontendIpFormat(List params) {
+        List<Room> list = new ArrayList<>();
+
+        for (int i = 0; i < params.size(); i++) {
+            String str = (String)params.get(i);
+            // 人数
+            String count = str.substring(str.lastIndexOf(":")+1);
+            // ip
+            String ip = str.substring(0, str.indexOf(":"));
+
+
+            Room room = new Room();
+            room.setRegion(FileUtils.getValue(ip));
+            room.setStatus(0);
+            room.setCount(Integer.valueOf(count));
+            list.add(room);
+        }
+        return list;
+    }
+
+    // 处理返回前端数据ip转换对应教室,固定数量
+    public static List frontendIpFormat2(List params) {
+        // 接收正常返回的ip
+        HashMap<Object, Room> resultMap = new HashMap<>();
+
+        for (int i = 0; i < params.size(); i++) {
+            String str = (String)params.get(i);
+            // 人数
+            String count = str.substring(str.lastIndexOf(":")+1);
+            // ip
+            String ip = str.substring(0, str.indexOf(":"));
+
+            Room room = new Room();
+            room.setRegion(FileUtils.getValue(ip));
+            room.setStatus(0); // 0:正常
+            room.setCount(Integer.valueOf(count));
+            resultMap.put(ip, room);
+        }
+
+        // 获取配置文件id列表
+        Set propertiesKey = FileUtils.getPropertiesKey();
+
+        // 返回结果集
+        List<Room> list = new ArrayList<>();
+        for (Object str: propertiesKey) {
+            // 匹配的
+            if (resultMap.containsKey(str)){
+                list.add(resultMap.get(str));
+            } else {
+                // 不匹配的
+                Room room = new Room();
+                room.setRegion(FileUtils.getValue(str.toString()));
+                room.setStatus(1) ; // 1:异常
+                room.setCount(0);
+                list.add(room);
+            }
+        }
+        log.info("frontend result: {}", list);
+        return list;
+    }
+
 
 
 
@@ -83,7 +145,8 @@ public class DataFormatUtils {
 
 
     public static void main(String[] args) {
-        String a = "1231:55";
+        String a = "192.168.1.123:55";
         System.out.println(a.substring(a.lastIndexOf(":")+1));
+        System.out.println(a.substring(0, a.indexOf(":")));
     }
 }

+ 29 - 2
src/main/java/com/fd/util/FileUtils.java

@@ -7,7 +7,10 @@ import org.springframework.util.ResourceUtils;
 import java.io.*;
 import java.net.URL;
 import java.net.URLDecoder;
+import java.util.Arrays;
+import java.util.List;
 import java.util.Properties;
+import java.util.Set;
 
 /**
  * Created by dell on 2019/4/1.
@@ -83,7 +86,7 @@ public class FileUtils {
         FileInputStream in = null;
         try {
             assert resource != null;
-            log.info(resource.getPath());
+//            log.info(resource.getPath());
             in = new FileInputStream(resource.getPath());
             prop.load(in);
         } catch (IOException e) {
@@ -92,10 +95,34 @@ public class FileUtils {
         return prop.getProperty(key);
     }
 
+
+    /**
+     * 获取配置文件所有key
+     */
+    public static Set getPropertiesKey(){
+        Properties prop = new Properties();
+        URL resource = FileUtils.class.getClassLoader().getResource("ip.properties");
+        FileInputStream in = null;
+        try {
+            assert resource != null;
+//            log.info(resource.getPath());
+            in = new FileInputStream(resource.getPath());
+            prop.load(in);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        Set<String> set = prop.stringPropertyNames();
+        return set;
+    }
+
     public static void main(String[] args) {
-        System.out.println(getValue("192.168.1.2"));
+//        Set key = getKey();
+//        List<Set> sets = Arrays.asList(key);
+
     }
 
+
     /**
      * 测试读取文件
      */

+ 1 - 1
src/main/java/com/fd/util/PythonUtils.java

@@ -18,7 +18,7 @@ public class PythonUtils {
 
     // 命令行调用python中间件
     public static List connect(String exePath, String command) {
-        log.info("run connect");
+//        log.info("run connect");
         String[] cmdArr = new String[] {exePath, command};
 
         Process process = null;

+ 13 - 10
src/main/resources/ip.properties

@@ -1,10 +1,13 @@
-192.168.1.1=101
-192.168.1.2=102
-192.168.1.3=103
-192.168.1.4=104
-192.168.1.5=105
-192.168.1.6=106
-192.168.1.7=107
-192.168.1.8=108
-192.168.1.9=109
-192.168.1.10=110
+# value 楼,楼层,教室号
+192.168.1.1=1,02,01
+192.168.1.2=1,02,02
+192.168.2.1=2,01,02
+192.168.2.2=2,01,03
+192.168.3.1=3,01,01
+192.168.3.2=3,01,02
+192.168.3.3=3,01,03
+192.168.0.0=3,01,03
+192.168.0.123=3,01,02
+127.0.0.1=3,02,02
+192.168.0.249=2,01,02
+