From e0626aa1d807d0a318017db5e719bd01d6fed738 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=B2=BE=E7=BE=8E=E7=A7=91=E6=8A=80?=
<9145550+jmkeji@user.noreply.gitee.com>
Date: Fri, 19 Jun 2026 03:19:27 +0800
Subject: [PATCH] jefe 0619
---
.idea/compiler.xml | 1 +
.idea/encodings.xml | 2 +
.idea/misc.xml | 1 +
web_group/pom.xml | 13 +
.../com/group/service/GroupRoomService.java | 219 +++++++----
.../java/com/group/service/HttpClient.java | 220 -----------
.../java/com/group/service/ISocketLayer.java | 67 ----
.../main/java/com/group/service/Message.java | 47 ---
.../com/group/service/MessageResponse.java | 17 -
.../java/com/group/service/NetManager.java | 107 ------
.../java/com/group/service/SocketCode.java | 46 ---
.../java/com/group/service/TaurusClient.java | 355 ------------------
.../java/com/group/service/ThreadManager.java | 123 ------
.../java/com/group/service/io/IOHandler.java | 251 -------------
.../java/com/group/service/io/ISocket.java | 113 ------
.../java/com/group/service/io/LagMonitor.java | 104 -----
.../java/com/group/service/io/Packet.java | 20 -
.../com/group/service/io/SocketEngine.java | 160 --------
.../com/group/service/io/SocketState.java | 13 -
.../java/com/group/service/io/SocketTcp.java | 156 --------
.../group/service/io/SystemController.java | 177 ---------
.../group/service/io/TSocketException.java | 23 --
web_group/target/ROOT.war | Bin 8860056 -> 12569572 bytes
.../com/group/service/GroupRoomService.class | Bin 28236 -> 29094 bytes
.../com/group/service/HttpClient$1.class | Bin 1032 -> 0 bytes
.../com/group/service/HttpClient$2.class | Bin 762 -> 0 bytes
.../com/group/service/HttpClient.class | Bin 8601 -> 0 bytes
.../com/group/service/ISocketLayer.class | Bin 874 -> 0 bytes
.../classes/com/group/service/Message.class | Bin 638 -> 0 bytes
.../com/group/service/MessageResponse.class | Bin 383 -> 0 bytes
.../com/group/service/NetManager.class | Bin 3267 -> 0 bytes
.../com/group/service/SocketCode.class | Bin 1509 -> 0 bytes
.../com/group/service/TaurusClient$1.class | Bin 1703 -> 0 bytes
.../com/group/service/TaurusClient$2.class | Bin 2658 -> 0 bytes
.../com/group/service/TaurusClient$3.class | Bin 2736 -> 0 bytes
.../com/group/service/TaurusClient$4.class | Bin 1038 -> 0 bytes
.../com/group/service/TaurusClient$5.class | Bin 812 -> 0 bytes
.../TaurusClient$ConnectionProtocol.class | Bin 1194 -> 0 bytes
.../service/TaurusClient$NetClientEvent.class | Bin 526 -> 0 bytes
.../com/group/service/TaurusClient.class | Bin 8164 -> 0 bytes
.../com/group/service/ThreadManager$1.class | Bin 653 -> 0 bytes
.../com/group/service/ThreadManager$2.class | Bin 652 -> 0 bytes
.../service/ThreadManager$MessgaeThread.class | Bin 721 -> 0 bytes
.../com/group/service/ThreadManager.class | Bin 3978 -> 0 bytes
.../io/IOHandler$PacketReadState.class | Bin 1366 -> 0 bytes
.../com/group/service/io/IOHandler.class | Bin 6525 -> 0 bytes
.../com/group/service/io/ISocket$1.class | Bin 685 -> 0 bytes
.../com/group/service/io/ISocket.class | Bin 3048 -> 0 bytes
.../com/group/service/io/LagMonitor.class | Bin 3064 -> 0 bytes
.../classes/com/group/service/io/Packet.class | Bin 365 -> 0 bytes
.../com/group/service/io/SocketEngine$1.class | Bin 827 -> 0 bytes
.../com/group/service/io/SocketEngine.class | Bin 6112 -> 0 bytes
.../com/group/service/io/SocketState.class | Bin 1139 -> 0 bytes
.../com/group/service/io/SocketTcp$1.class | Bin 652 -> 0 bytes
.../com/group/service/io/SocketTcp$2.class | Bin 652 -> 0 bytes
.../com/group/service/io/SocketTcp.class | Bin 5242 -> 0 bytes
.../group/service/io/SystemController$1.class | Bin 927 -> 0 bytes
.../group/service/io/SystemController$2.class | Bin 974 -> 0 bytes
.../group/service/io/SystemController.class | Bin 5884 -> 0 bytes
.../group/service/io/TSocketException.class | Bin 512 -> 0 bytes
.../ROOT/WEB-INF/lib/fastjson2-2.0.43.jar | Bin 0 -> 2001287 bytes
.../ROOT/WEB-INF/lib/httpclient5-5.4.4.jar | Bin 0 -> 911620 bytes
.../ROOT/WEB-INF/lib/httpcore5-5.3.4.jar | Bin 0 -> 908601 bytes
.../ROOT/WEB-INF/lib/httpcore5-h2-5.3.4.jar | Bin 0 -> 241692 bytes
.../ROOT/WEB-INF/lib/slf4j-api-1.7.25.jar | Bin 41203 -> 0 bytes
.../ROOT/WEB-INF/lib/slf4j-api-1.7.36.jar | Bin 0 -> 41125 bytes
.../com/group/service/GroupRoomService.class | Bin 28236 -> 29094 bytes
.../com/group/service/HttpClient$1.class | Bin 1032 -> 0 bytes
.../com/group/service/HttpClient$2.class | Bin 762 -> 0 bytes
.../com/group/service/HttpClient.class | Bin 8601 -> 0 bytes
.../com/group/service/ISocketLayer.class | Bin 874 -> 0 bytes
.../classes/com/group/service/Message.class | Bin 638 -> 0 bytes
.../com/group/service/MessageResponse.class | Bin 383 -> 0 bytes
.../com/group/service/NetManager.class | Bin 3267 -> 0 bytes
.../com/group/service/SocketCode.class | Bin 1509 -> 0 bytes
.../com/group/service/TaurusClient$1.class | Bin 1703 -> 0 bytes
.../com/group/service/TaurusClient$2.class | Bin 2658 -> 0 bytes
.../com/group/service/TaurusClient$3.class | Bin 2736 -> 0 bytes
.../com/group/service/TaurusClient$4.class | Bin 1038 -> 0 bytes
.../com/group/service/TaurusClient$5.class | Bin 812 -> 0 bytes
.../TaurusClient$ConnectionProtocol.class | Bin 1194 -> 0 bytes
.../service/TaurusClient$NetClientEvent.class | Bin 526 -> 0 bytes
.../com/group/service/TaurusClient.class | Bin 8164 -> 0 bytes
.../com/group/service/ThreadManager$1.class | Bin 653 -> 0 bytes
.../com/group/service/ThreadManager$2.class | Bin 652 -> 0 bytes
.../service/ThreadManager$MessgaeThread.class | Bin 721 -> 0 bytes
.../com/group/service/ThreadManager.class | Bin 3978 -> 0 bytes
.../io/IOHandler$PacketReadState.class | Bin 1366 -> 0 bytes
.../com/group/service/io/IOHandler.class | Bin 6525 -> 0 bytes
.../com/group/service/io/ISocket$1.class | Bin 685 -> 0 bytes
.../com/group/service/io/ISocket.class | Bin 3048 -> 0 bytes
.../com/group/service/io/LagMonitor.class | Bin 3064 -> 0 bytes
.../classes/com/group/service/io/Packet.class | Bin 365 -> 0 bytes
.../com/group/service/io/SocketEngine$1.class | Bin 827 -> 0 bytes
.../com/group/service/io/SocketEngine.class | Bin 6112 -> 0 bytes
.../com/group/service/io/SocketState.class | Bin 1139 -> 0 bytes
.../com/group/service/io/SocketTcp$1.class | Bin 652 -> 0 bytes
.../com/group/service/io/SocketTcp$2.class | Bin 652 -> 0 bytes
.../com/group/service/io/SocketTcp.class | Bin 5242 -> 0 bytes
.../group/service/io/SystemController$1.class | Bin 927 -> 0 bytes
.../group/service/io/SystemController$2.class | Bin 974 -> 0 bytes
.../group/service/io/SystemController.class | Bin 5884 -> 0 bytes
.../group/service/io/TSocketException.class | Bin 512 -> 0 bytes
.../compile/default-compile/createdFiles.lst | 48 +--
.../compile/default-compile/inputFiles.lst | 31 +-
105 files changed, 185 insertions(+), 2129 deletions(-)
delete mode 100644 web_group/src/main/java/com/group/service/HttpClient.java
delete mode 100644 web_group/src/main/java/com/group/service/ISocketLayer.java
delete mode 100644 web_group/src/main/java/com/group/service/Message.java
delete mode 100644 web_group/src/main/java/com/group/service/MessageResponse.java
delete mode 100644 web_group/src/main/java/com/group/service/NetManager.java
delete mode 100644 web_group/src/main/java/com/group/service/SocketCode.java
delete mode 100644 web_group/src/main/java/com/group/service/TaurusClient.java
delete mode 100644 web_group/src/main/java/com/group/service/ThreadManager.java
delete mode 100644 web_group/src/main/java/com/group/service/io/IOHandler.java
delete mode 100644 web_group/src/main/java/com/group/service/io/ISocket.java
delete mode 100644 web_group/src/main/java/com/group/service/io/LagMonitor.java
delete mode 100644 web_group/src/main/java/com/group/service/io/Packet.java
delete mode 100644 web_group/src/main/java/com/group/service/io/SocketEngine.java
delete mode 100644 web_group/src/main/java/com/group/service/io/SocketState.java
delete mode 100644 web_group/src/main/java/com/group/service/io/SocketTcp.java
delete mode 100644 web_group/src/main/java/com/group/service/io/SystemController.java
delete mode 100644 web_group/src/main/java/com/group/service/io/TSocketException.java
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/HttpClient$1.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/HttpClient$2.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/HttpClient.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/ISocketLayer.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/Message.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/MessageResponse.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/NetManager.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/SocketCode.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient$1.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient$2.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient$3.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient$4.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient$5.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient$ConnectionProtocol.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient$NetClientEvent.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/TaurusClient.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/ThreadManager$1.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/ThreadManager$2.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/ThreadManager$MessgaeThread.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/ThreadManager.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/IOHandler$PacketReadState.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/IOHandler.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/ISocket$1.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/ISocket.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/LagMonitor.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/Packet.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SocketEngine$1.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SocketEngine.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SocketState.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SocketTcp$1.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SocketTcp$2.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SocketTcp.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SystemController$1.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SystemController$2.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/SystemController.class
delete mode 100644 web_group/target/ROOT/WEB-INF/classes/com/group/service/io/TSocketException.class
create mode 100644 web_group/target/ROOT/WEB-INF/lib/fastjson2-2.0.43.jar
create mode 100644 web_group/target/ROOT/WEB-INF/lib/httpclient5-5.4.4.jar
create mode 100644 web_group/target/ROOT/WEB-INF/lib/httpcore5-5.3.4.jar
create mode 100644 web_group/target/ROOT/WEB-INF/lib/httpcore5-h2-5.3.4.jar
delete mode 100644 web_group/target/ROOT/WEB-INF/lib/slf4j-api-1.7.25.jar
create mode 100644 web_group/target/ROOT/WEB-INF/lib/slf4j-api-1.7.36.jar
delete mode 100644 web_group/target/classes/com/group/service/HttpClient$1.class
delete mode 100644 web_group/target/classes/com/group/service/HttpClient$2.class
delete mode 100644 web_group/target/classes/com/group/service/HttpClient.class
delete mode 100644 web_group/target/classes/com/group/service/ISocketLayer.class
delete mode 100644 web_group/target/classes/com/group/service/Message.class
delete mode 100644 web_group/target/classes/com/group/service/MessageResponse.class
delete mode 100644 web_group/target/classes/com/group/service/NetManager.class
delete mode 100644 web_group/target/classes/com/group/service/SocketCode.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient$1.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient$2.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient$3.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient$4.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient$5.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient$ConnectionProtocol.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient$NetClientEvent.class
delete mode 100644 web_group/target/classes/com/group/service/TaurusClient.class
delete mode 100644 web_group/target/classes/com/group/service/ThreadManager$1.class
delete mode 100644 web_group/target/classes/com/group/service/ThreadManager$2.class
delete mode 100644 web_group/target/classes/com/group/service/ThreadManager$MessgaeThread.class
delete mode 100644 web_group/target/classes/com/group/service/ThreadManager.class
delete mode 100644 web_group/target/classes/com/group/service/io/IOHandler$PacketReadState.class
delete mode 100644 web_group/target/classes/com/group/service/io/IOHandler.class
delete mode 100644 web_group/target/classes/com/group/service/io/ISocket$1.class
delete mode 100644 web_group/target/classes/com/group/service/io/ISocket.class
delete mode 100644 web_group/target/classes/com/group/service/io/LagMonitor.class
delete mode 100644 web_group/target/classes/com/group/service/io/Packet.class
delete mode 100644 web_group/target/classes/com/group/service/io/SocketEngine$1.class
delete mode 100644 web_group/target/classes/com/group/service/io/SocketEngine.class
delete mode 100644 web_group/target/classes/com/group/service/io/SocketState.class
delete mode 100644 web_group/target/classes/com/group/service/io/SocketTcp$1.class
delete mode 100644 web_group/target/classes/com/group/service/io/SocketTcp$2.class
delete mode 100644 web_group/target/classes/com/group/service/io/SocketTcp.class
delete mode 100644 web_group/target/classes/com/group/service/io/SystemController$1.class
delete mode 100644 web_group/target/classes/com/group/service/io/SystemController$2.class
delete mode 100644 web_group/target/classes/com/group/service/io/SystemController.class
delete mode 100644 web_group/target/classes/com/group/service/io/TSocketException.class
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 902b116..c6d8bfe 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -10,6 +10,7 @@
+
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
index 31ce7e1..07ea0aa 100644
--- a/.idea/encodings.xml
+++ b/.idea/encodings.xml
@@ -3,6 +3,8 @@
+
+
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 11b353a..e743370 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -12,6 +12,7 @@
+
diff --git a/web_group/pom.xml b/web_group/pom.xml
index 7b0b3bc..8f84f74 100644
--- a/web_group/pom.xml
+++ b/web_group/pom.xml
@@ -14,6 +14,13 @@
+
+
+ org.apache.httpcomponents.client5
+ httpclient5
+ 5.4.4
+
+
junit
junit
@@ -21,6 +28,12 @@
test
+
+ com.alibaba.fastjson2
+ fastjson2
+ 2.0.43
+
+
com.data
diff --git a/web_group/src/main/java/com/group/service/GroupRoomService.java b/web_group/src/main/java/com/group/service/GroupRoomService.java
index b849c1b..9f7d656 100644
--- a/web_group/src/main/java/com/group/service/GroupRoomService.java
+++ b/web_group/src/main/java/com/group/service/GroupRoomService.java
@@ -1,5 +1,11 @@
package com.group.service;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -1063,6 +1069,8 @@ public class GroupRoomService {
String key = createGroupRoom(session, groupId, pid);
resData = publicJoinRoom(groupId, session, key, platform);
}
+
+ /* robot jefe
Jedis jedis11 = Redis.use("group1_db11").getJedis();
try {
jedis11.zremrangeByScore(grooms_key, 0, 0);
@@ -1093,6 +1101,8 @@ public class GroupRoomService {
} finally {
jedis11.close();
}
+
+ */
return resData;
}
@@ -1106,80 +1116,161 @@ public class GroupRoomService {
log.info("sendRobotData :"+roomid+"groupid:"+groupid+"robot_host:"+robot_host);
+ Jedis js1 = Redis.use("group1_db3").getJedis();
+ try {
- CompletableFuture future = CompletableFuture.supplyAsync(() -> {
- // 执行任务
- Jedis js1 = Redis.use("group1_db3").getJedis();
- String flag = js1.get("roomsend"+roomid);
- if(flag!=null){
- js1.close();
+ String flag = js1.get("roomsend" + roomid);
+ if (flag != null) {
return null;
}
- js1.set("roomsend"+roomid,1+"");
- js1.expire("roomsend"+roomid,5);
- try {
- Thread eventThread = new Thread(() -> {
- while (true) {
- NetManager.processEvents();
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- break;
- } catch (Exception e) {
- }
- }
- }, "tstse");
+ js1.set("roomsend" + roomid, 1 + "");
+ js1.expire("roomsend" + roomid, 5);
- eventThread.setDaemon(true); // 设置为守护线程
- eventThread.start();
- int robotid = 0;
- //
- Set jsRobot = js1.smembers("robots");
-
- String wokelock = "wokelock";
- for (String key : jsRobot) {
- String tmp = js1.get(wokelock+key);
- if(StringUtil.isEmpty(tmp)){
- robotid = Integer.parseInt(key);
- }
+ int robotid = 0;
+ Set jsRobot = js1.smembers("robots");
+ log.info("jsRobot" + jsRobot);
+ String wokelock = "wokelock";
+ for (String key : jsRobot) {
+ String tmp = js1.get(wokelock + key);
+ if (StringUtil.isEmpty(tmp)) {
+ robotid = Integer.parseInt(key);
}
-
- if(robotid!=0){
- js1.set(wokelock+robotid, String.valueOf(1));
- js1.expire(wokelock+robotid,2);
- TaurusClient client = new TaurusClient(robot_host, "games"+robotid, TaurusClient.ConnectionProtocol.Tcp);
- client.setSession("abbccccd"+robotid+roomid);
- client.connect();
- sleep(1500);
- ITObject params = TObject.newInstance();
- params.putString("roomid",roomid);
- params.putInt("groupid",groupid);
- params.putInt("robotid",robotid);
- System.out.println("ssss");
- System.out.println(client.isConnected());
- log.info("=====================sendRobotData发送前 :"+roomid+"robotid:"+robotid);
- Message msg= client.send("225", params, response -> {
- System.out.println("abcd");
- });
- log.info("=====================sendRobotData发送了 :"+roomid+"robotid:"+robotid);
- sleep(10000);
- eventThread.setDaemon(false);
- client.killConnection();
- }
- eventThread.yield();
- log.info("sendRobotData :"+roomid+"robotid:"+robotid);
- js1.close();
- }catch (Exception e){
- js1.close();
- }finally {
- js1.close();
}
- return "执行结果";
- });
+
+
+// int robotid = 0;
+// Map jsRobot = js1.hgetAll("{robot426149}" + gameId);
+// String wokelock = "wokelock";
+// for (String key : jsRobot.keySet()) {
+// String tmp = js1.get(wokelock + key);
+// if (StringUtil.isEmpty(tmp)) {
+// robotid = Integer.parseInt(key);
+// break;
+// }
+// }
+
+ if (robotid == 0) {
+ log.info("sendRobotData 没有可用机器人 roomid:" + roomid);
+ return null;
+ }
+
+ //设置机器人占用标记
+ js1.set(wokelock + robotid, String.valueOf(1));
+ js1.expire(wokelock + robotid, 2);
+
+// js1.expire(wokelock + robotid, 900);
+
+ //通过 HTTP 同步调用机器人服务的 225 协议入口
+ sleep(1000);
+ String url = buildRobotHttpUrl(robot_host);
+ String body = buildJoinRoomBody(robotid, roomid, groupid);
+ String resp = httpPostJson(url, body, 5000);
+ log.info("sendRobotData roomid:" + roomid + " robotid:" + robotid + " resp:" + resp);
+ } catch (Exception e) {
+ log.error("sendRobotData 异常 roomid:" + roomid, e);
+ } finally {
+ js1.close();
+ }
//client.killConnection();
return null;
}
+
+ /**
+ * 根据机器人 TCP 地址推导 HTTP URL
+ * 规则:HTTP 端口 = TCP 端口 + 1000(与 robot_mj_hz 的 Config.HTTP_SERVER_PORT 一致)
+ * 例:robot_host="192.168.0.32:8722" → "http://192.168.0.32:9722/robot/joinRoom"
+ */
+ private static String buildRobotHttpUrl(String robot_host) {
+ String host;
+ int tcpPort;
+ int colonIdx = robot_host.indexOf(':');
+ if (colonIdx > 0) {
+ host = robot_host.substring(0, colonIdx);
+ tcpPort = Integer.parseInt(robot_host.substring(colonIdx + 1));
+ } else {
+ host = robot_host;
+ tcpPort = 8722;
+ }
+ int httpPort = tcpPort + 1000;
+ return "http://" + host + ":" + httpPort + "/robot/joinRoom";
+ }
+
+ /**
+ * 构造 225 协议请求体 JSON
+ */
+ private static String buildJoinRoomBody(int robotid, String roomid, int groupid) {
+ StringBuilder sb = new StringBuilder(64);
+ sb.append("{\"robotid\":").append(robotid)
+ .append(",\"roomid\":\"").append(roomid).append("\"")
+ .append(",\"groupid\":").append(groupid)
+ .append("}");
+ return sb.toString();
+ }
+
+ /**
+ * 通过 JDK HttpURLConnection 发送 POST JSON 请求(同步)
+ * 替代原 TaurusClient + CompletableFuture + eventThread 异步 TCP 方式
+ *
+ * @param urlStr 完整 URL
+ * @param jsonBody 请求体 JSON 字符串
+ * @param timeoutMs 连接与读取超时(毫秒)
+ * @return 响应体字符串;失败时返回错误描述
+ */
+ private static String httpPostJson(String urlStr, String jsonBody, int timeoutMs) {
+ HttpURLConnection conn = null;
+ try {
+ URL url = new URL(urlStr);
+ conn = (HttpURLConnection) url.openConnection();
+ conn.setRequestMethod("POST");
+ conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
+ conn.setConnectTimeout(timeoutMs);
+ conn.setReadTimeout(timeoutMs);
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+
+ //写入请求体
+ byte[] bodyBytes = jsonBody.getBytes(StandardCharsets.UTF_8);
+ try (OutputStream os = conn.getOutputStream()) {
+ os.write(bodyBytes);
+ os.flush();
+ }
+
+ //读取响应
+ int code = conn.getResponseCode();
+ InputStream is = (code >= 200 && code < 300) ? conn.getInputStream() : conn.getErrorStream();
+ String resp = readAll(is);
+ if (code < 200 || code >= 300) {
+ log.warn("httpPostJson 失败 url:" + urlStr + " code:" + code + " resp:" + resp);
+ return "HTTP " + code + ": " + resp;
+ }
+ return resp;
+ } catch (Exception e) {
+ log.error("httpPostJson 异常 url:" + urlStr, e);
+ return "ERROR:" + e.getMessage();
+ } finally {
+ if (conn != null) {
+ conn.disconnect();
+ }
+ }
+ }
+
+ /**
+ * 读取输入流为字符串
+ */
+ private static String readAll(InputStream in) throws Exception {
+ if (in == null) return "";
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ byte[] buf = new byte[1024];
+ int n;
+ while ((n = in.read(buf)) > 0) {
+ baos.write(buf, 0, n);
+ }
+ in.close();
+ return new String(baos.toByteArray(), StandardCharsets.UTF_8);
+ }
+
+
/**
* 删除房间
*
diff --git a/web_group/src/main/java/com/group/service/HttpClient.java b/web_group/src/main/java/com/group/service/HttpClient.java
deleted file mode 100644
index 6106162..0000000
--- a/web_group/src/main/java/com/group/service/HttpClient.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package com.group.service;
-
-import com.group.service.TaurusClient.ConnectionProtocol;
-import com.taurus.core.entity.ITObject;
-import com.taurus.core.entity.TObject;
-import com.taurus.core.util.*;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.ConnectException;
-import java.net.HttpURLConnection;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.util.LinkedList;
-import java.util.Queue;
-
-
-/**
- * Http缃戠粶璇锋眰澶勭悊绫?
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class HttpClient implements ISocketLayer {
- private static final Logger logger = Logger.getLogger(HttpClient.class);
- private static final byte[] NULL_BYTES = new byte[0];
- private static final String _Method = "POST";
- private static final String _ContentTypeName = "Content-Type";
- private static final String _ContentType = "application/octet-stream";
- private static final String _Result = "$r";
- private static final String _Param = "$p";
- private static final String _Session = "$s";
- private static final String _Version = "$v";
- String _url;
- String _session_id = "";
-
- final Queue _actionQueue = new LinkedList();
-
-
- public HttpClient(String url) {
- _url = url;
- }
-
- private void __sendMsg(Message msg) {
- byte[] bytes = NULL_BYTES;
- ITObject _data = TObject.newInstance();
- _data.putString(_Session, _session_id);
- _data.putInt(_Version, NetManager.VERSION);
- if (msg.useText && msg.param == null) {
- if (StringUtil.isEmpty(msg.textParam)) {
- msg.param = TObject.newInstance();
- } else {
- try {
- msg.param = TObject.newFromJsonData(msg.textParam);
- } catch (Exception e) {
- msg.param = TObject.newInstance();
- }
- }
- }
- _data.putTObject(_Param, msg.param);
- ByteArray buff = new ByteArray(_data.toBinary());
- try {
- buff.compress();
- } catch (Exception e) {
- logger.error(e);
- }
- bytes = buff.bytes();
-
- __requestAsync(msg, bytes);
- }
-
- private void __requestAsync(final Message msg,byte[] bytes) {
- OutputStream out = null;
- InputStream in = null;
- int code = 500;
- HttpURLConnection conn = null;
- try {
-
- URL realUrl = new URL(_url + msg.command);
- conn = (HttpURLConnection) realUrl.openConnection();
- conn.setDoOutput(true);
- conn.setDoInput(true);
- conn.setRequestProperty(_ContentTypeName, _ContentType);
- conn.setUseCaches(false);// Post 璇锋眰涓嶈兘浣跨敤缂撳瓨
- conn.setRequestMethod(_Method);
- conn.setConnectTimeout(NetManager.TIMEOUT_TIME * 1000);
- conn.setReadTimeout(NetManager.TIMEOUT_TIME * 1000);
- conn.connect();
-
-
- out = conn.getOutputStream();
- out.write(bytes);
- if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
- in = conn.getInputStream();
- bytes = Utils.uncompress(in);
- if (bytes!=null) {
-
- ITObject tem = TObject.newFromBinaryData(bytes);
- int result = tem.getInt(_Result);
-
- if (result == 0) {
- ITObject _param = tem.getTObject(_Param);
- msg.param = _param;
- if(msg.useText) {
- msg.textParam = _param.toJson();
- }
- }
- code = result;
-
- }
- }
- } catch (SocketTimeoutException e) {
- logger.error(e);
- code = 102;
- } catch (ConnectException ex1) {
- logger.error(ex1);
- code = 101;
- } catch (Exception ex2) {
- logger.error(ex2);
- code = 500;
- }finally {
- try {
- if (out != null) {
- out.close();
- }
- } catch (IOException ex) {
- logger.error(ex);
- }
- try {
- if (in != null) {
- in.close();
- }
- }catch (IOException ex) {
- logger.error(ex);
- }
- if(conn!=null) {
- conn.disconnect();
- }
- }
- if (msg.callback != null) {
- final MessageResponse response = new MessageResponse();
- response.messageData = msg;
- response.returnCode = code;
- enqueueActionForDispatch(new Runnable() {
- @Override
- public void run() {
- msg.callback.action(response);
- }
- });
- }
-
- }
-
- @Override
- public void connect(String ip, String game) {
-
- }
-
- @Override
- public void disconnect() {
-
- }
-
- private void enqueueActionForDispatch(Runnable action) {
- synchronized (_actionQueue) {
- _actionQueue.offer(action);
- }
- }
-
- @Override
- public void processEvent() {
- while (true) {
- Runnable myAction;
- synchronized (_actionQueue) {
- if (_actionQueue.size() <= 0) {
- break;
- }
- myAction = _actionQueue.poll();
- }
- myAction.run();
- }
- }
-
- public void write(final Message msg) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- __sendMsg(msg);
- }
- }).start();
- }
-
- public int getAveragePingTime() {
- return 1000;
- }
-
- public void setSession(String session) {
- _session_id = session == null ? StringUtil.Empty : session;
- }
-
- public String getSession() {
- return _session_id;
-
- }
-
- @Override
- public void setOnConnect(ICallback onConnect) {
-
- }
-
- @Override
- public void setOnEvent(ICallback onEvent) {
-
- }
-
- @Override
- public ConnectionProtocol getProtocol() {
- return ConnectionProtocol.Web;
- }
-}
diff --git a/web_group/src/main/java/com/group/service/ISocketLayer.java b/web_group/src/main/java/com/group/service/ISocketLayer.java
deleted file mode 100644
index a28c35b..0000000
--- a/web_group/src/main/java/com/group/service/ISocketLayer.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package com.group.service;
-
-import com.group.service.TaurusClient.ConnectionProtocol;
-import com.taurus.core.util.ICallback;
-
-/**
- * 网络协议处理通用接口
- * @author daixiwei daixiwei15@126.com
- *
- */
-public interface ISocketLayer {
- /**
- * 连接服务器
- * @param ip
- * @param game
- */
- public void connect(String ip, String game);
-
- /**
- * 断开连接
- */
- public void disconnect();
-
- /**
- * 处理事件
- */
- public void processEvent();
-
- /**
- * 发送消息
- * @param msg
- */
- public void write(Message msg);
-
- /**
- * get Protocol type
- * @return
- */
- public ConnectionProtocol getProtocol();
-
- /**
- * 设置连接状态回调
- */
- public void setOnConnect(ICallback onConnect);
-
-
- /**
- * 设置事件消息回调E
- */
- public void setOnEvent(ICallback onEvent);
-
- /**
- * 网络延时
- */
- public int getAveragePingTime();
-
- /**
- * 获取服务器Session字符
- */
- public String getSession();
-
- /**
- * 设置服务器Session字符
- * @param session
- */
- public void setSession(String session);
-}
diff --git a/web_group/src/main/java/com/group/service/Message.java b/web_group/src/main/java/com/group/service/Message.java
deleted file mode 100644
index 11e57d1..0000000
--- a/web_group/src/main/java/com/group/service/Message.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.group.service;
-
-import com.taurus.core.entity.ITObject;
-import com.taurus.core.util.ICallback;
-
-/**
- * 网络协议消息包
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class Message {
- /**
- * 使用文本,不转换ITObject
- */
- public boolean useText;
- /**
- * 网络协议指令Key
- */
- public String command;
-
- /**
- * 参数
- */
- public ITObject param;
- /**
- * 文本数据
- */
- public String textParam;
-
- /**
- * 网络消息回调
- */
- public ICallback callback;
- /**
- * 自定义参数
- */
- public Object data;
- /**
- * 网络包最后写入时间
- */
- public long lastTime;
- /**
- * 网络包返回匹配的GID
- */
- public int gid;
-
-}
diff --git a/web_group/src/main/java/com/group/service/MessageResponse.java b/web_group/src/main/java/com/group/service/MessageResponse.java
deleted file mode 100644
index fa79180..0000000
--- a/web_group/src/main/java/com/group/service/MessageResponse.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.group.service;
-
-/**
- * 缃戠粶娑堟伅鍥炶皟鏁版嵁瀵硅薄
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class MessageResponse {
- /**
- * 娑堟伅鏁版嵁
- */
- public Message messageData;
- /**
- * 杩斿洖缁撴瀯鍊?
- */
- public int returnCode;
-}
diff --git a/web_group/src/main/java/com/group/service/NetManager.java b/web_group/src/main/java/com/group/service/NetManager.java
deleted file mode 100644
index b4c119a..0000000
--- a/web_group/src/main/java/com/group/service/NetManager.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package com.group.service;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 网络管理对象
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class NetManager {
-
- private static List _clientList = new ArrayList();
- private static Map _clientMap = new HashMap();
-
- /**
- * 网络超时时间
- */
- public static int TIMEOUT_TIME = 10;
- /**
- * 网络版本号
- */
- public static int VERSION = 10;
- public static boolean debug_print = false;
-
- static void addNetClient(TaurusClient net) {
- if (net == null) {
- throw new RuntimeException("TaurusClient is null, it can't be added.");
- }
- if (_clientMap.containsKey(net.getId())) {
- throw new RuntimeException("A client with id: " + net.getId() + " already exists! Controller can't be added: " + net);
- }
- synchronized (_clientList) {
- _clientMap.put(net.getId(), net);
- _clientList.add(net);
- }
-
- }
-
- /**
- * The process events
- */
- public static void processEvents() {
- for (int i = 0; i < _clientList.size(); ++i) {
- TaurusClient nc = _clientList.get(i);
- if (nc._kill){
- synchronized (_clientList) {
- _clientMap.remove(nc.getId());
- _clientList.remove(nc);
- }
- i--;
- continue;
- }else{
- nc.processEvent();
- }
- }
-
- }
-
- /**
- * 返回指定的NetClient
- * @param id
- * @return
- */
- public static TaurusClient getNetClient(int id) {
- for (int i = 0; i < _clientList.size(); ++i) {
- TaurusClient nc = _clientList.get(i);
- if (nc.getId() == id)
- return nc;
- }
- return null;
- }
-
- /**
- * 断开指定连接
- * @param id
- */
- public static void killConnection(int id) {
- for (int i = 0; i < _clientList.size(); ++i) {
- TaurusClient nc = _clientList.get(i);
- if (nc.getId() == id) {
- nc.killConnection();
- synchronized (_clientList) {
- _clientMap.remove(id);
- _clientList.remove(nc);
- }
- break;
- }
- }
- }
-
- /**
- * 断开所有连接
- */
- public static void killAllConnection() {
- synchronized (_clientList) {
- for (TaurusClient nc : _clientList) {
- nc.killConnection();
- }
- _clientList.clear();
- _clientMap.clear();
- }
-
- }
-}
diff --git a/web_group/src/main/java/com/group/service/SocketCode.java b/web_group/src/main/java/com/group/service/SocketCode.java
deleted file mode 100644
index a35b639..0000000
--- a/web_group/src/main/java/com/group/service/SocketCode.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.group.service;
-
-/**
- * Socket code
- * @author daixiwei daixiwei15@126.com
- *
- */
-public enum SocketCode {
- /**
- * 杩炴帴鎴愬姛
- */
- Connect,
- Disconnect,
- /**
- * 鏈煡寮傚父
- */
- Exception,
- /**
- * 杩炴帴鏈嶅姟寮傚父
- */
- ExceptionOnConnect,
- /**
- * 鍙戦€佹暟鎹祦閿欒
- */
- SendError,
- /**
- * 鎺ユ敹鏈嶅姟鍣ㄦ暟鎹祦寮傚父
- */
- ExceptionOnReceive,
- /**
- * 鏈嶅姟鍣ㄨ繛鎺ヨ秴鏃?
- */
- TimeoutDisconnect,
- /**
- * 鏈嶅姟鍣ㄦ柇寮€杩炴帴
- */
- DisconnectByServer,
- /**
- * 瀹㈡埛绔綉缁滃紓甯?
- */
- NetworkException,
- /**
- * 杩炴帴瀹夊叏寮傚父锛屼竴鑸负闃茬伀澧欓樆姝?
- */
- SecurityExceptionOnConnect
-}
diff --git a/web_group/src/main/java/com/group/service/TaurusClient.java b/web_group/src/main/java/com/group/service/TaurusClient.java
deleted file mode 100644
index 016dfde..0000000
--- a/web_group/src/main/java/com/group/service/TaurusClient.java
+++ /dev/null
@@ -1,355 +0,0 @@
-package com.group.service;
-
-import com.group.service.io.SocketEngine;
-import com.taurus.core.entity.ITObject;
-import com.taurus.core.events.Event;
-import com.taurus.core.events.EventDispatcher;
-import com.taurus.core.events.IEventListener;
-import com.taurus.core.util.ICallback;
-import com.taurus.core.util.Logger;
-
-
-import java.util.HashMap;
-import java.util.Map;
-
-
-/**
- * 缃戠粶鏍稿績鍔熻兘澶勭悊绫?
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class TaurusClient {
- private static final Logger logger = Logger.getLogger(TaurusClient.class);
- private int _id;
- private boolean _connect;
- private String _gameId;
- private String _currentIp;
-
- private ISocketLayer _scoket;
- private ThreadManager _threadManager;
-
- private EventDispatcher _dispatcher;
- private Map> _responseMap;
- volatile boolean _kill = false;
- private static int _tempID;
- private int _protocolCompression=100;
-
- private static int _getValidID() {
- return ++_tempID;
- }
-
- /**
- *
- * @param host
- * @param game
- * @param protocol
- */
- public TaurusClient(String host, String game, ConnectionProtocol protocol) {
- ISocketLayer socket = null;
- switch (protocol) {
- case Tcp:
- socket = new SocketEngine(this);
- break;
- case Web:
- socket = new HttpClient(host);
- _connect = true;
- break;
- default:
- socket = new SocketEngine(this);
- break;
- }
- __initialize(host, game, socket);
- }
-
- /**
- *
- * @param host
- * @param game
- * @param socket
- * @param protocol
- */
- public TaurusClient(String host, String game, ISocketLayer socket) {
- __initialize(host, game, socket);
-
- }
-
- /**
- * 娣诲姞浜嬩欢
- * @param eventType
- * @param listener
- */
- public void addEventListener(String eventType, IEventListener listener) {
- _dispatcher.addEventListener(eventType, listener);
- }
-
- /**
- * 绉婚櫎鎵€鏈変簨浠?
- */
- public void removeAllListener() {
- _dispatcher.removeAllListener();
- }
-
- /**
- * 绉婚櫎鎸囧畾浜嬩欢
- * @param eventType
- * @param listener
- */
- public void removeEventListener(String eventType, IEventListener listener) {
- _dispatcher.removeEventListener(eventType, listener);
- }
-
- private void __initialize(String host, String game, ISocketLayer socket) {
- _dispatcher = new EventDispatcher();
- _responseMap = new HashMap>();
- _id = _getValidID();
- NetManager.addNetClient(this);
- _currentIp = host;
- _gameId = game;
- _threadManager = new ThreadManager();
- _threadManager.start();
- _scoket = socket;
- _scoket.setOnConnect(new ICallback() {
- @Override
- public void action(SocketCode code) {
- if (code == SocketCode.Connect)
- _connect = true;
- else
- _connect = false;
- Event evt = new Event(NetClientEvent.Connect);
- evt.setParameter("code", code);
- _dispatcher.dispatchEvent(evt);
- }
- });
- _scoket.setOnEvent(new ICallback() {
- @Override
- public void action(Message msg) {
- if (_connect) {
- Event evt = new Event(NetClientEvent.OnEvent);
- evt.setParameter("msg", msg);
- _dispatcher.dispatchEvent(evt);
- if (NetManager.debug_print){
- String str = getProtocol() == ConnectionProtocol.Web ? "WEB" : "TCP";
- String data_str = msg.useText ? msg.textParam : (msg.param != null ? msg.param.toJson() : "null");
- logger.debug("Event [" + str + "->" + msg.command + "] data:" + data_str);
- }
- }
- }
- });
- }
-
- /**
- * 杩炴帴鏈嶅姟鍣?
- */
- public void connect() {
- _scoket.connect(_currentIp, _gameId);
- }
-
- /**
- * Kill net connection.
- */
- public void killConnection() {
- removeAllListener();
- _responseMap.clear();
- _threadManager.stop();
- _scoket.disconnect();
- _connect = false;
- _kill = true;
- }
-
- /**
- * 鍙戦€佺綉缁滄秷鎭寘
- * @param msg 娑堟伅鏁版嵁瀵硅薄
- */
- protected void send(Message msg) {
- if (msg == null)
- return;
- if (NetManager.debug_print) {
- String str = getProtocol() == ConnectionProtocol.Web ? "WEB" : "TCP";
- String data_str = msg.useText ? msg.textParam : (msg.param != null ? msg.param.toJson() : "null");
- str = "Requst [" + str + "->" + msg.command + "] ->data:" + data_str;
- logger.debug(str);
- }
- if (msg.callback != null) {
- _responseMap.put(msg, msg.callback);
- msg.callback = new ICallback() {
-
- @Override
- public void action(MessageResponse response) {
- ICallback callback = _responseMap.get(response.messageData);
- if (callback == null) {
- return;
- }
- if (NetManager.debug_print){
- String str = getProtocol() == ConnectionProtocol.Web ? "WEB" : "TCP";
- String data_str = msg.useText ? msg.textParam : (msg.param != null ? msg.param.toJson() : "null");
- str = "Response [" + str + "->" + msg.command + "] ->result:"+ response.returnCode + " param:" + data_str;
- logger.debug(str);
- }
- _responseMap.remove(response.messageData);
- callback.action(response);
- }
-
- };
- }
-
- _threadManager.enqueueSend(new ICallback() {
- @Override
- public void action(Message msg) {
- sendData(msg);
- }
- }, msg);
- }
-
-
- /**
- * 鍙戦€佺綉缁滄秷鎭寘
- * @param cmd 缃戠粶鍗忚鎸囦护Key
- * @param param 鍙傛暟
- * @param callback 缃戠粶娑堟伅鍥炶皟
- * @return
- */
- public Message send(String cmd, ITObject param, ICallback callback) {
- Message msg = new Message();
- msg.useText = false;
- msg.command = cmd;
- msg.param = param;
- msg.callback = callback;
- this.send(msg);
- return msg;
- }
-
- /**
- * 鍙戦€佺綉缁滄秷鎭寘
- * @param cmd 缃戠粶鍗忚鎸囦护Key
- * @param text JSON 鏂囨湰
- * @param callback 缃戠粶娑堟伅鍥炶皟
- * @return
- */
- public Message sendText(String cmd, String text, ICallback callback) {
- Message msg = new Message();
- msg.command = cmd;
- msg.textParam = text;
- msg.callback = callback;
- msg.useText = true;
- this.send(msg);
- return msg;
- }
-
- /**
- * 鍙戦€佹暟鎹嚎绋嬫柟娉?
- * @param message
- */
- private void sendData(Message msg) {
- _scoket.write(msg);
- }
-
- /**
- * 澶勭悊浜嬩欢
- */
- void processEvent() {
- if(_scoket!=null) {
- _scoket.processEvent();
- }
- }
-
- /**
- * 娓呯悊鍝嶅簲鍥炶皟
- */
- public void clearResponse() {
- _responseMap.clear();
- }
-
- /**
- * The net client id
- * @return
- */
- public int getId() {
-
- return _id;
-
- }
-
- /**
- * The curren ip
- * @return
- */
- public String getCurrentIp() {
- return _currentIp;
- }
-
- /**
- * The curren Game ID
- * @return
- */
- public String getGameID() {
- return _gameId;
- }
-
- /**
- * 缃戠粶鏄惁宸茶繛鎺?
- * @return
- */
- public boolean isConnected() {
- return _connect;
- }
-
- /**
- * 褰撳墠缃戠粶绫诲瀷
- * @return
- */
- public ConnectionProtocol getProtocol() {
- return _scoket.getProtocol();
- }
-
- /**
- * 缃戠粶寤舵椂
- * @return
- */
- public int getAveragePingTime() {
- return _scoket.getAveragePingTime();
- }
-
- /**
- * 鑾峰彇鏈嶅姟鍣⊿ession瀛楃
- * @return
- */
- public String getSession() {
- return _scoket.getSession();
- }
-
- /**
- * 璁剧疆鏈嶅姟鍣⊿ession瀛楃
- * @param session
- */
- public void setSession(String session) {
- _scoket.setSession(session);
- }
-
- /**
- * 璁剧疆鍘嬬缉闃€鍊?
- * @param protocolCompression
- */
- public void setProtocolCompression(int protocolCompression) {
- _protocolCompression = protocolCompression;
- }
-
- /**
- * 鑾峰彇鍘嬬缉闃€鍊?
- *
- * @return
- */
- public int getProtocolCompression() {
- return _protocolCompression;
- }
-
-
- public static enum ConnectionProtocol {
- Tcp, Web,
- }
-
- public static class NetClientEvent {
- public static final String Connect = "connect";
-
- public static final String OnEvent = "onevent";
- }
-}
diff --git a/web_group/src/main/java/com/group/service/ThreadManager.java b/web_group/src/main/java/com/group/service/ThreadManager.java
deleted file mode 100644
index b9e2078..0000000
--- a/web_group/src/main/java/com/group/service/ThreadManager.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.group.service;
-
-import com.taurus.core.util.ICallback;
-
-import java.util.LinkedList;
-import java.util.Queue;
-import java.util.Stack;
-
-
-
-/**
- * 网络(读/写) 线程管理
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class ThreadManager {
- class MessgaeThread {
- public ICallback _dataDelegate;
-
- public Message _message;
- }
-
- private boolean _running = false;
- private Thread _outThread;
- private boolean _outHasQueuedItems = false;
- private Queue _outThreadQueue = new LinkedList();
- private Object _outQueueLocker = new Object();
- private Stack pool = new Stack();
-
- private MessgaeThread MessgaeThreadGet() {
- if (pool.size() > 0) {
- MessgaeThread msg = pool.pop();
- return msg;
- } else
- return new MessgaeThread();
- }
-
- private void MessgaeThreadReturn(MessgaeThread value) {
- pool.push(value);
- value._dataDelegate = null;
- value._message = null;
- }
-
- private static void sleep(int ms) {
- try {
- Thread.sleep(ms);
- } catch (InterruptedException e) {
-
- }
- }
-
- private void outThread() {
- while (_running) {
- sleep(5);
- if (_outHasQueuedItems) {
- Object obj = _outQueueLocker;
- synchronized (obj) {
- while (_outThreadQueue.size() > 0) {
- MessgaeThread item = _outThreadQueue.poll();
- processOutItem(item);
- }
- _outHasQueuedItems = false;
- }
- }
- }
- }
-
- private void processOutItem(MessgaeThread item) {
- ICallback _dataDelegate = item._dataDelegate;
- Message message = item._message;
- MessgaeThreadReturn(item);
- if (_dataDelegate != null) {
- _dataDelegate.action(message);
- }
- }
-
- public void start() {
- if (_running) {
- return;
- }
- _running = true;
- if (_outThread == null) {
- _outThread = new Thread(new Runnable() {
- @Override
- public void run() {
- outThread();
- }
- });
- _outThread.start();
- _outThread.setName("WriteMessage");
- }
- }
-
- public void stop() {
- Thread thread = new Thread(new Runnable() {
- @Override
- public void run() {
- stopThread();
- }
- });
- thread.start();
- }
-
- private void stopThread() {
- _running = false;
-
- if (_outThread != null) {
- _outThread.interrupt();
- }
- _outThread = null;
- }
-
- public void enqueueSend(ICallback callback, Message message) {
- MessgaeThread hashtable = MessgaeThreadGet();
- hashtable._dataDelegate = callback;
- hashtable._message = message;
- Object obj = _outQueueLocker;
- synchronized (obj) {
- _outThreadQueue.offer(hashtable);
- _outHasQueuedItems = true;
- }
- }
-}
diff --git a/web_group/src/main/java/com/group/service/io/IOHandler.java b/web_group/src/main/java/com/group/service/io/IOHandler.java
deleted file mode 100644
index ce90f90..0000000
--- a/web_group/src/main/java/com/group/service/io/IOHandler.java
+++ /dev/null
@@ -1,251 +0,0 @@
-package com.group.service.io;
-
-import com.group.service.SocketCode;
-import com.taurus.core.entity.ITObject;
-import com.taurus.core.entity.TObject;
-import com.taurus.core.util.ByteArray;
-import com.taurus.core.util.Logger;
-import com.taurus.core.util.Utils;
-
-import java.io.IOException;
-
-/**
- * 鍗忚鍖呭瓧鑺傛祦瑙f瀽
- *
- * @author daixiwei daixiwei15@126.com
- *
- */
-class IOHandler {
- private final Logger logger = Logger.getLogger(IOHandler.class);
- private static final String ACTION_ID = "a";
- private static final String PARAM_ID = "p";
- static final int INT_BYTE_SIZE = 4;
-
- private static final ByteArray EMPTY_BUFFER = new ByteArray();
- private int _skipBytes = 0;
- private ByteArray _buffer;
- private int _expectedLength = -1;
- private boolean _compressed = false;
-
- private SocketEngine _engine;
- private SystemController _controller;
-
- /**
- * 璇诲彇鐘舵€?
- */
- private PacketReadState _readState = PacketReadState.WAIT_NEW_PACKET;
-
- IOHandler(SocketEngine client, SystemController controller) {
- _engine = client;
- _controller = controller;
- }
-
- /**
- *
- * @param data
- * @return
- * @throws IOException
- */
- private ByteArray handleDataSize(ByteArray data) throws Exception {
- int num = data.readInt();
- int pos = INT_BYTE_SIZE;
- if (num != -1) {
- _expectedLength = num;
- data = resizeByteArray(data, pos, data.length() - pos);
- _readState = PacketReadState.WAIT_DATA;
- return data;
- }
- _readState = PacketReadState.WAIT_DATA_SIZE_FRAGMENT;
- _buffer.writeBytes(data.bytes());
- data = EMPTY_BUFFER;
- return data;
- }
-
- /**
- *
- * @param data
- * @return
- * @throws IOException
- */
- private ByteArray handleDataSizeFragment(ByteArray data) throws Exception {
- int count = INT_BYTE_SIZE - _buffer.length();
- if (data.length() >= count) {
- _buffer.writeBytes(data.bytes(), 0, count);
- int num2 = INT_BYTE_SIZE;
- ByteArray array = new ByteArray();
- array.writeBytes(_buffer.bytes(), 0, num2);
- array.position(0);
- int num3 = array.readInt();
- _expectedLength = num3;
- _buffer = new ByteArray();
- _readState = PacketReadState.WAIT_DATA;
- if (data.length() > count) {
- data = resizeByteArray(data, count, data.length() - count);
- return data;
- }
- data = EMPTY_BUFFER;
- return data;
- }
- _buffer.writeBytes(data.bytes());
- data = EMPTY_BUFFER;
- return data;
- }
-
- /**
- *
- * @param data
- * @return
- */
- private ByteArray handleInvalidData(ByteArray data) {
- if (_skipBytes == 0) {
- _readState = PacketReadState.WAIT_NEW_PACKET;
- return data;
- }
- int pos = Math.min(data.length(), _skipBytes);
- data = resizeByteArray(data, pos, data.length() - pos);
- _skipBytes -= pos;
- return data;
- }
-
- /**
- *
- * @param data
- * @return
- */
- private ByteArray handleNewPacket(ByteArray data) throws Exception {
- _buffer = new ByteArray();
- _expectedLength = -1;
- _compressed = data.readByte() > 0;
- data = resizeByteArray(data, 1, data.length() - 1);
- _readState = PacketReadState.WAIT_DATA_SIZE;
- return data;
- }
-
- /**
- *
- * @param data
- * @return
- */
- private ByteArray handlePacketData(ByteArray data) throws Exception {
- int count = _expectedLength - _buffer.length();
- boolean flag = data.length() > count;
- ByteArray array = new ByteArray(data.bytes());
- try {
- if (data.length() >= count) {
- _buffer.writeBytes(data.bytes(), 0, count);
- if (_compressed) {
- _buffer.uncompress();
- }
- dispatchRequest(_buffer);
- _readState = PacketReadState.WAIT_NEW_PACKET;
- } else {
- _buffer.writeBytes(data.bytes());
- }
- if (flag) {
- data = resizeByteArray(data, count, data.length() - count);
- return data;
- }
- data = EMPTY_BUFFER;
- } catch (Exception exception) {
- logger.error("Error handling data ", exception);
- _skipBytes = count;
- _readState = PacketReadState.INVALID_DATA;
- return array;
- }
- return data;
- }
-
- private void dispatchRequest(ByteArray _buffer) throws IOException {
- ITObject requestObject = TObject.newFromBinaryData(_buffer.bytes());
- Packet packet = new Packet();
- if (requestObject.isNull(ACTION_ID)) {
- throw new IOException("Request rejected: No Action ID in request!");
- }
- packet.actionID = requestObject.getByte(ACTION_ID);
- packet.parameters = requestObject.getTObject(PARAM_ID);
- _controller.handlePacket(packet);
- }
-
- /**
- *
- * @param data
- * @throws IOException
- */
- public void onDataRead(ByteArray data) throws IOException {
- if (data.length() == 0) {
- throw new IOException("Unexpected empty packet data: no readable bytes available!");
- }
-
- data.position(0);
- try {
- while (data.length() > 0) {
- if (_readState == PacketReadState.WAIT_NEW_PACKET) {
- data = handleNewPacket(data);
- } else {
- if (_readState == PacketReadState.WAIT_DATA_SIZE) {
- data = handleDataSize(data);
- continue;
- }
- if (_readState == PacketReadState.WAIT_DATA_SIZE_FRAGMENT) {
- data = handleDataSizeFragment(data);
- continue;
- }
- if (_readState == PacketReadState.WAIT_DATA) {
- data = handlePacketData(data);
- continue;
- }
- if (_readState == PacketReadState.INVALID_DATA) {
- data = handleInvalidData(data);
- }
- }
- }
- } catch (Exception e) {
- this.logger.error(e);
- }
-
- }
-
- /**
- *
- * @param packet
- * @throws IOException
- */
- public void onDataWrite(Packet packet) throws IOException {
- ByteArray binData = new ByteArray();
-
- ITObject obj2 = new TObject();
- obj2.putByte(ACTION_ID, (byte) packet.actionID);
- obj2.putTObject(PARAM_ID, packet.parameters);
- byte[] array2 = obj2.toBinary();
- boolean compression = array2.length > _engine.getProtocolCompression();
- if (compression) {
- array2 = Utils.compress(array2);
- }
- binData.writeByte((byte) (compression ? 1 : 0));
- binData.writeInt(array2.length);
- binData.writeBytes(array2);
-
- if (_engine._socket.isConnected()) {
- if (!_engine._socket.send(binData.bytes())) {
- _engine.enqueueStatusCallback(SocketCode.SendError);
- }
- }
- }
-
- /**
- *
- * @param array
- * @param pos
- * @param len
- * @return
- */
- private ByteArray resizeByteArray(ByteArray array, int pos, int len) {
- byte[] dst = new byte[len];
- System.arraycopy(array.bytes(), pos, dst, 0, len);
- return new ByteArray(dst);
- }
-
- static enum PacketReadState {
- WAIT_NEW_PACKET, WAIT_DATA_SIZE, WAIT_DATA_SIZE_FRAGMENT, WAIT_DATA, INVALID_DATA
- }
-}
diff --git a/web_group/src/main/java/com/group/service/io/ISocket.java b/web_group/src/main/java/com/group/service/io/ISocket.java
deleted file mode 100644
index baabdea..0000000
--- a/web_group/src/main/java/com/group/service/io/ISocket.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package com.group.service.io;
-
-import com.group.service.SocketCode;
-import com.taurus.core.util.Logger;
-import com.taurus.core.util.StringUtil;
-
-/**
- * Socket核心基类
- * @author daixiwei daixiwei15@126.com
- *
- */
-public abstract class ISocket {
- protected static final Logger logger = Logger.getLogger(ISocket.class);
- SocketEngine _engine;
- /**
- * 当前socket状态
- */
- public volatile SocketState state = SocketState.Disconnected;
- /**
- * 服务器地址
- */
- protected String serverAddress;
- /**
- * 服务器端口
- */
- protected int serverPort;
-
- /**
- * 网络链接状态
- * @return
- */
- public boolean isConnected() {
- return state == SocketState.Connected;
- }
-
- public ISocket(SocketEngine peerBase) {
- if (peerBase == null) {
- throw new RuntimeException("Can't init without peer");
- }
- this._engine = peerBase;
- }
-
- public boolean connect() {
- boolean result;
- if (state != SocketState.Disconnected) {
- logger.error("Calling connect when the socket is not disconnected");
- result = false;
- } else if (_engine == null) {
- result = false;
- } else if (!tryParseAddress(_engine.getServerAddress())) {
- logger.error("Failed parsing address: " + _engine.getServerAddress());
- result = false;
- } else {
- result = true;
- }
- return result;
- }
-
- /**
- * 断开连接
- * @return
- */
- public abstract boolean disconnect();
-
- /**
- * 发送流数据
- * @param data
- * @return
- */
- public abstract boolean send(byte[] data);
-
- protected void handleException(SocketCode statusCode) {
- state = SocketState.Disconnecting;
- _engine.enqueueStatusCallback(statusCode);
- _engine.enqueueActionForDispatch(new Runnable() {
- @Override
- public void run() {
- disconnect();
- }
- });
- }
-
- /**
- * 解析网络地址
- * @param addressAndPort
- * @param address
- * @param port
- * @return
- */
- protected boolean tryParseAddress(String addressAndPort) {
- boolean result = true;
- if (StringUtil.isEmpty(addressAndPort)) {
- result = false;
- } else {
- int num = addressAndPort.lastIndexOf(':');
- if (num <= 0) {
- result = false;
- } else if (addressAndPort.indexOf(':') != num && (!addressAndPort.contains("[") || !addressAndPort.contains("]"))) {
- result = false;
- } else {
- serverAddress = addressAndPort.substring(0, num);
- String s = addressAndPort.substring(num + 1);
- try {
- serverPort = Integer.parseInt(s);
- } catch (Exception e) {
- result = false;
- }
- }
- }
- return result;
- }
-
-}
diff --git a/web_group/src/main/java/com/group/service/io/LagMonitor.java b/web_group/src/main/java/com/group/service/io/LagMonitor.java
deleted file mode 100644
index 5eeca79..0000000
--- a/web_group/src/main/java/com/group/service/io/LagMonitor.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.group.service.io;
-
-import com.taurus.core.util.Logger;
-
-import java.io.IOException;
-import java.util.*;
-
-
-/**
- * 网络监听/心跳
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class LagMonitor extends TimerTask {
- private static final Logger logger = Logger.getLogger(LagMonitor.class);
- private int _averagePingTime;
- private Timer _pollTimer;
- private int _queueSize;
- private int _interval;
- private boolean _run;
- private SocketEngine _engine;
- private List _valueQueue;
- private Queue write_queue = new LinkedList();
-
- public LagMonitor(SocketEngine engine, int interval, int queueSize) {
- if (interval < 1) {
- interval = 1;
- }
- _engine = engine;
- _valueQueue = new ArrayList();
- _queueSize = queueSize;
- _pollTimer = new Timer();
- _interval = interval * 1000;
- _averagePingTime = 1000;
- }
-
- public void fnPingPong() {
- long w_time = write_queue.poll();
- long item = System.currentTimeMillis() - w_time;
- if (_valueQueue.size() >= _queueSize) {
- _valueQueue.remove(0);
- }
- _valueQueue.add(item);
- if (_valueQueue.size() == 0) {
- _averagePingTime = 0;
- }
- int num = 0;
- for (int i = 0; i < _valueQueue.size(); ++i) {
- num += _valueQueue.get(i);
- }
- _averagePingTime = (num / _valueQueue.size());
- }
-
- /**
- * 启动监听
- */
- public void start() {
- if (!isRunning()) {
- this._run = true;
- _pollTimer.scheduleAtFixedRate(this, 0, _interval);
- }
- }
-
- /**
- * 停止监听
- */
- public void stop() {
- if (isRunning()) {
- this._run = false;
- _pollTimer.purge();
- }
- }
-
- public void destroy() {
- stop();
- _pollTimer.cancel();
- _pollTimer = null;
- _engine = null;
- }
-
- /**
- * 平均Ping的时间
- * @return
- */
- public int getAveragePingTime() {
- return _averagePingTime;
-
- }
-
- public boolean isRunning() {
- return _run;
-
- }
-
- @Override
- public void run() {
- try {
- _engine._controller.sendPingPong();
- write_queue.offer(System.currentTimeMillis());
- } catch (IOException e) {
- logger.error(e);
- }
- }
-}
diff --git a/web_group/src/main/java/com/group/service/io/Packet.java b/web_group/src/main/java/com/group/service/io/Packet.java
deleted file mode 100644
index 574fce0..0000000
--- a/web_group/src/main/java/com/group/service/io/Packet.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.group.service.io;
-
-import com.taurus.core.entity.ITObject;
-
-/**
- * 网络协议数据包
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class Packet {
-
- /**
- * 协议包ID
- */
- public int actionID;
- /**
- * 参数数据
- */
- public ITObject parameters;
-}
diff --git a/web_group/src/main/java/com/group/service/io/SocketEngine.java b/web_group/src/main/java/com/group/service/io/SocketEngine.java
deleted file mode 100644
index 68e07fb..0000000
--- a/web_group/src/main/java/com/group/service/io/SocketEngine.java
+++ /dev/null
@@ -1,160 +0,0 @@
-package com.group.service.io;
-
-import com.group.service.*;
-import com.group.service.TaurusClient.ConnectionProtocol;
-import com.taurus.core.util.ICallback;
-import com.taurus.core.util.Logger;
-
-import java.io.IOException;
-import java.util.LinkedList;
-import java.util.Queue;
-
-/**
- * SocketEngine
- *
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class SocketEngine implements ISocketLayer {
- private static final Logger logger = Logger.getLogger(SocketEngine.class);
-
- ISocket _socket;
- private String _sessionToken;
- private String _serverAddress;
-
- private ICallback _onConnect;
- ICallback _onEvent;
- private Queue _actionQueue = new LinkedList();
-
- SystemController _controller;
- LagMonitor _lagMonitor;
- IOHandler _packetHandler;
- TaurusClient _client;
-
- public SocketEngine(TaurusClient client) {
- _socket = new SocketTcp(this);
- _controller = new SystemController(this);
- _packetHandler = new IOHandler(this, _controller);
- _lagMonitor = new LagMonitor(this, NetManager.TIMEOUT_TIME, 10);
- }
-
- @Override
- public void connect(String ip, String game) {
- _serverAddress = ip;
- _socket.connect();
- }
-
- @Override
- public void disconnect() {
- _socket.disconnect();
- if (_lagMonitor != null)
- _lagMonitor.destroy();
- _lagMonitor = null;
- }
-
- @Override
- public void processEvent() {
- if (_socket.isConnected() && _controller.isTimeOut()) {
- if (_onConnect != null)
- _onConnect.action(SocketCode.TimeoutDisconnect);
- return;
- }
-
- while (true) {
- Runnable myAction;
- synchronized (_actionQueue) {
- if (_actionQueue.size() <= 0) {
- break;
- }
- myAction = _actionQueue.poll();
- }
- myAction.run();
- }
- }
-
- public void write(Message msg) {
- try {
- _controller.sendRequest(msg);
- } catch (IOException e) {
- logger.error(e);
- }
- }
-
- void onStatusChanged(SocketCode statusCode) {
- if (statusCode != SocketCode.Connect) {
- _socket.disconnect();
- this.disconnect();
- }
- System.out.println("status : " + statusCode);
- logger.info("status : " + statusCode);
- if (statusCode == SocketCode.Connect) {
- this.onHandshake();
- } else {
- if (_onConnect != null)
- _onConnect.action(statusCode);
- }
- }
-
- void onHandshake() {
- _controller.refreshTime();
- _lagMonitor.start();
- if (_onConnect != null)
- _onConnect.action(SocketCode.Connect);
- }
-
- void enqueueActionForDispatch(Runnable action) {
- synchronized (_actionQueue) {
- _actionQueue.offer(action);
- }
- }
-
- void enqueueStatusCallback(final SocketCode statusValue) {
- synchronized (_actionQueue) {
- _actionQueue.offer(new Runnable() {
- @Override
- public void run() {
- onStatusChanged(statusValue);
- }
- });
- }
- }
-
-
-
-
- public String getServerAddress() {
- return _serverAddress;
- }
-
- @Override
- public ConnectionProtocol getProtocol() {
- return ConnectionProtocol.Tcp;
- }
-
- public int getAveragePingTime() {
- return _lagMonitor != null ? _lagMonitor.getAveragePingTime() : 1000;
- }
-
- public void setSession(String session) {
- _sessionToken = session == null ? "" : session;
- }
-
- public String getSession() {
- return _sessionToken;
-
- }
-
- @Override
- public void setOnConnect(ICallback onConnect) {
- _onConnect = onConnect;
- }
-
- @Override
- public void setOnEvent(ICallback onEvent) {
- _onEvent = onEvent;
- }
-
- public int getProtocolCompression() {
- return 100;
- }
-}
diff --git a/web_group/src/main/java/com/group/service/io/SocketState.java b/web_group/src/main/java/com/group/service/io/SocketState.java
deleted file mode 100644
index 6b0046e..0000000
--- a/web_group/src/main/java/com/group/service/io/SocketState.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.group.service.io;
-
-/**
- * 缃戠粶鐘舵€佹灇涓?
- * @author daixiwei daixiwei15@126.com
- *
- */
-public enum SocketState{
- Disconnected,
- Connecting,
- Connected,
- Disconnecting
-}
diff --git a/web_group/src/main/java/com/group/service/io/SocketTcp.java b/web_group/src/main/java/com/group/service/io/SocketTcp.java
deleted file mode 100644
index b0d0ee4..0000000
--- a/web_group/src/main/java/com/group/service/io/SocketTcp.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package com.group.service.io;
-
-import com.group.service.NetManager;
-import com.group.service.SocketCode;
-import com.taurus.core.util.ByteArray;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-
-/**
- * Tcp协议 Socket核心类
- * @author daixiwei daixiwei15@126.com
- *
- */
-class SocketTcp extends ISocket {
- private static final int READ_BUFFER_SIZE = 0x1000;
- private byte[] _byteBuffer = new byte[READ_BUFFER_SIZE];
-
- private Socket _connection;
- private final Object _syncer = new Object();
-
- public SocketTcp(SocketEngine npeer) {
- super(npeer);
- }
-
- @Override
- public boolean connect() {
- if (!super.connect()) {
- return false;
- } else {
- state = SocketState.Connecting;
- Thread t = new Thread(new Runnable() {
- @Override
- public void run() {
- connectThread();
- }
- });
- t.setName("mpnet connect thread");
- t.start();
- return true;
- }
- }
-
- private void connectThread() {
- try {
- SocketAddress remoteAddr = new InetSocketAddress(serverAddress, super.serverPort);
- _connection = new Socket();
- _connection.setTcpNoDelay(true);
- _connection.connect(remoteAddr, NetManager.TIMEOUT_TIME * 1000);
- state = SocketState.Connected;
- _engine.enqueueStatusCallback(SocketCode.Connect);
- } catch (Exception ex) {
- try {
- if (_connection != null)
- _connection.close();
- } catch (Exception e) {
- logger.error("Connection close error", e);
- }
- logger.error("Connection error", ex);
- handleException(SocketCode.ExceptionOnConnect);
- return;
- }
- Thread _thrSocketReader = new Thread(new Runnable() {
- @Override
- public void run() {
- __read();
- }
- });
- _thrSocketReader.start();
- }
-
- @Override
- public boolean disconnect() {
- if (state == SocketState.Disconnected)
- return false;
- state = SocketState.Disconnecting;
- synchronized (_syncer) {
- if (_connection != null) {
- try {
- _connection.close();
- } catch (Exception ex) {
- logger.error("Disconnect error", ex);
- }
- _connection = null;
- }
- }
- state = SocketState.Disconnected;
- return true;
- }
-
- @Override
- public boolean send(byte[] data) {
- return __writeSocket(data);
- }
-
- private boolean __writeSocket(byte[] buf) {
- if (_connection == null || state != SocketState.Connected) {
- logger.error("Trying to write to disconnected socket");
- return false;
- } else {
- try {
- OutputStream outStream = _connection.getOutputStream();
- outStream.write(buf);
- outStream.flush();
- } catch (Exception exception2) {
- logger.error("General error writing to socket", exception2);
- handleException(SocketCode.SendError);
- return false;
- }
- }
- return true;
- }
-
- private void __read() {
- int size = 0;
- while (state == SocketState.Connected) {
- try {
- try {
- InputStream inputStream = _connection.getInputStream();
- size = inputStream.read(_byteBuffer);
- } catch (Exception ex) {
- throw new TSocketException(SocketCode.ExceptionOnReceive);
- }
- if (size == 0 || size == -1) {
-// System.out.println("socket----报错--------111111--------");
- throw new TSocketException(SocketCode.DisconnectByServer);
- }
- __handleBinaryData(_byteBuffer, size);
-
- } catch (TSocketException ex3) {
- if (state != SocketState.Disconnecting && state.ordinal() > SocketState.Disconnected.ordinal()) {
- logger.error("Receiving failed.: ", ex3);
- super.handleException(ex3.socketCode);
- }
- } catch (Exception ex4) {
- if (state != SocketState.Disconnecting && state.ordinal() > SocketState.Disconnected.ordinal()) {
- logger.error("Receiving Exception: ", ex4);
- super.handleException(SocketCode.ExceptionOnReceive);
- }
- }
- }
-
- this.disconnect();
- }
-
- private void __handleBinaryData(byte[] buf, int size) throws IOException {
- byte[] dst = new byte[size];
- System.arraycopy(buf, 0, dst, 0, size);
- ByteArray array = new ByteArray(dst);
- _engine._packetHandler.onDataRead(array);
- }
-}
diff --git a/web_group/src/main/java/com/group/service/io/SystemController.java b/web_group/src/main/java/com/group/service/io/SystemController.java
deleted file mode 100644
index ec47b8d..0000000
--- a/web_group/src/main/java/com/group/service/io/SystemController.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package com.group.service.io;
-
-import com.group.service.Message;
-import com.group.service.MessageResponse;
-import com.group.service.NetManager;
-import com.taurus.core.entity.ITObject;
-import com.taurus.core.entity.TObject;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 协议处理控制器
- *
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class SystemController {
- public static final String CONNECT_TOKE = "$t";
- public static final String CONNECT_PROT_COMPRESSION = "$pc";
- public static final String REQUEST_CMD = "$c";
- public static final String REQUEST_GID = "$gi";
- public static final String REQUEST_PARM = "$p";
- public static final String REQUEST_RESULT = "$r";
-
- /**
- * pingpong
- */
- public static final int ACTION_PINGPONG = 0;
- /**
- * 客户端请求
- */
- public static final int ACTION_REQUST_CMD = 1;
- /**
- * 服务器事件消息
- */
- public static final int ACTION_EVENT_CMD = 2;
-
- private SocketEngine _engine;
- private long _lastTime;
- private List _handleList = new ArrayList();
- private int _tempID;
-
- public SystemController(SocketEngine client) {
- _engine = client;
- _lastTime = System.currentTimeMillis();
- }
-
- private int _getValidID() {
- return ++_tempID;
- }
-
-
- public void handlePacket(Packet packet) {
- _lastTime = System.currentTimeMillis();
- switch (packet.actionID) {
- case ACTION_PINGPONG:
- fnPingPong(packet);
- break;
- case ACTION_REQUST_CMD:
- fnOperationResponse(packet);
- break;
- case ACTION_EVENT_CMD:
- fnOperationEvent(packet);
- break;
- }
- }
-
- void sendRequest(Message msg) throws IOException {
- Packet packet = new Packet();
- packet.actionID = SystemController.ACTION_REQUST_CMD;
- ITObject obj = TObject.newInstance();
- obj.putString(SystemController.REQUEST_CMD, msg.command);
- int gid = 0;
- if (msg.callback != null) {
- gid = _getValidID();
- msg.lastTime = System.currentTimeMillis();
- msg.gid = gid;
- synchronized (_handleList) {
- _handleList.add(msg);
- }
- }
- obj.putInt(SystemController.REQUEST_GID, gid);
- obj.putTObject(SystemController.REQUEST_PARM, msg.param);
- packet.parameters = obj;
- _engine._packetHandler.onDataWrite(packet);
- }
-
- void sendPingPong() throws IOException {
- Packet packet = new Packet();
- packet.actionID = SystemController.ACTION_PINGPONG;
- packet.parameters = TObject.newInstance();
- _engine._packetHandler.onDataWrite(packet);
- }
-
- private final void fnOperationResponse(final Packet packet) {
- final int gid = packet.parameters.getInt(REQUEST_GID);
- final int result = packet.parameters.getInt(REQUEST_RESULT);
- ITObject tem = null;
- if (packet.parameters.containsKey(REQUEST_PARM)) {
- tem = packet.parameters.getTObject(REQUEST_PARM);
- }
- final ITObject param = tem;
- _engine.enqueueActionForDispatch(new Runnable() {
- @Override
- public void run() {
- handleOperationResponse(result, gid, param);
- }
- });
- }
-
- private void handleOperationResponse(int result, int gid, ITObject param) {
- Message msg = null;
- int index = 0;
- int len = _handleList.size();
- if (gid > 0) {
- for (int i = 0; i < len; ++i) {
- if (gid == _handleList.get(i).gid) {
- msg = _handleList.get(i);
- index = i;
- break;
- }
- }
- }
-
- if (msg != null) {
- if (msg.callback != null) {
- MessageResponse response = new MessageResponse();
- msg.param = param;
- response.messageData = msg;
- response.returnCode = result;
- msg.callback.action(response);
- }
- synchronized (_handleList) {
- _handleList.remove(index);
- }
- }
- }
-
- private final void fnOperationEvent(Packet packet) {
- final String cmd = packet.parameters.getString(REQUEST_CMD);
- ITObject tem = null;
- if (packet.parameters.containsKey(REQUEST_PARM)) {
- tem = packet.parameters.getTObject(REQUEST_PARM);
- }
- final ITObject param = tem;
- _engine.enqueueActionForDispatch(new Runnable() {
- @Override
- public void run() {
- handleEvent(cmd, param);
- }
- });
- }
-
- void handleEvent(String cmd, ITObject param) {
- Message msg = new Message();
- msg.command = cmd;
- msg.param = param;
- if (_engine._onEvent != null)
- _engine._onEvent.action(msg);
- }
-
-
- private final void fnPingPong(Packet packet) {
- _engine._lagMonitor.fnPingPong();
- }
-
- public boolean isTimeOut() {
- return (System.currentTimeMillis() - _lastTime) / 1000 > NetManager.TIMEOUT_TIME;
- }
-
- public void refreshTime() {
- _lastTime = System.currentTimeMillis();
- }
-
-}
diff --git a/web_group/src/main/java/com/group/service/io/TSocketException.java b/web_group/src/main/java/com/group/service/io/TSocketException.java
deleted file mode 100644
index 3875a23..0000000
--- a/web_group/src/main/java/com/group/service/io/TSocketException.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.group.service.io;
-
-import com.group.service.SocketCode;
-
-/**
- * 缃戠粶閫氫俊寮傚父
- * @author daixiwei daixiwei15@126.com
- *
- */
-public class TSocketException extends Exception{
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
-
- public SocketCode socketCode;
-
- public TSocketException(SocketCode code) {
- socketCode = code;
- }
-
-}
diff --git a/web_group/target/ROOT.war b/web_group/target/ROOT.war
index c50d09c6ce06caa37a8a60460594bd99170ac521..8e97d2c14700a9e07423b55bb1596a543b4b5da6 100644
GIT binary patch
delta 3839292
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