From 5fb38f50ed4ff28d36d9cf09b8fb838e8ce232e2 Mon Sep 17 00:00:00 2001 From: dai_48k <1981669259@qq.com> Date: Sat, 20 Jan 2024 15:33:00 +0800 Subject: [PATCH] first commit --- .gitignore | 3 + client/src/META-INF/MANIFEST.MF | 3 + .../src/top/dreamcenter/go/client/Client.java | 78 +++++++++ .../top/dreamcenter/go/client/DataUtil.java | 37 +++++ .../top/dreamcenter/go/client/MainFrame.java | 145 ++++++++++++++++ client/src/top/dreamcenter/go/msg/Cross.java | 5 + client/src/top/dreamcenter/go/msg/KVPair.java | 16 ++ .../src/top/dreamcenter/go/msg/NewClick.java | 20 +++ server/src/META-INF/MANIFEST.MF | 3 + server/src/top/dreamcenter/go/msg/Cross.java | 5 + server/src/top/dreamcenter/go/msg/KVPair.java | 24 +++ .../src/top/dreamcenter/go/msg/NewClick.java | 29 ++++ .../dreamcenter/go/server/CalDataUtil.java | 155 ++++++++++++++++++ .../top/dreamcenter/go/server/DataUtil.java | 37 +++++ .../src/top/dreamcenter/go/server/Server.java | 42 +++++ .../top/dreamcenter/go/server/UserThread.java | 105 ++++++++++++ 16 files changed, 707 insertions(+) create mode 100644 .gitignore create mode 100644 client/src/META-INF/MANIFEST.MF create mode 100644 client/src/top/dreamcenter/go/client/Client.java create mode 100644 client/src/top/dreamcenter/go/client/DataUtil.java create mode 100644 client/src/top/dreamcenter/go/client/MainFrame.java create mode 100644 client/src/top/dreamcenter/go/msg/Cross.java create mode 100644 client/src/top/dreamcenter/go/msg/KVPair.java create mode 100644 client/src/top/dreamcenter/go/msg/NewClick.java create mode 100644 server/src/META-INF/MANIFEST.MF create mode 100644 server/src/top/dreamcenter/go/msg/Cross.java create mode 100644 server/src/top/dreamcenter/go/msg/KVPair.java create mode 100644 server/src/top/dreamcenter/go/msg/NewClick.java create mode 100644 server/src/top/dreamcenter/go/server/CalDataUtil.java create mode 100644 server/src/top/dreamcenter/go/server/DataUtil.java create mode 100644 server/src/top/dreamcenter/go/server/Server.java create mode 100644 server/src/top/dreamcenter/go/server/UserThread.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6374f7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +out/ +.idea/ +*.iml \ No newline at end of file diff --git a/client/src/META-INF/MANIFEST.MF b/client/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..9595d79 --- /dev/null +++ b/client/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: top.dreamcenter.go.client.Client + diff --git a/client/src/top/dreamcenter/go/client/Client.java b/client/src/top/dreamcenter/go/client/Client.java new file mode 100644 index 0000000..8ef5c8b --- /dev/null +++ b/client/src/top/dreamcenter/go/client/Client.java @@ -0,0 +1,78 @@ +package top.dreamcenter.go.client; + +import top.dreamcenter.go.msg.Cross; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; + +public class Client { + + + public static void main(String[] args) { + + try { + Socket socket = new Socket("127.0.0.1", 1919); + + ObjectInputStream oi = new ObjectInputStream(socket.getInputStream()); + ObjectOutputStream os = new ObjectOutputStream(socket.getOutputStream()); + + + new MainFrame(oi, os); + + } catch (IOException e) { + e.printStackTrace(); + } + + } + + public static void sendMsg(ObjectOutputStream os, Object obj) { + try { + os.writeObject(obj); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static Object recMsg(ObjectInputStream oi){ + try { + return oi.readObject(); + } catch (ClassNotFoundException | IOException e) { + e.printStackTrace(); + return null; + } + } + + public static void printMap(Cross[][] map, Cross now){ + System.out.println(); + int width = map.length - 1; + System.out.println("O A B C D E F G H I"); + for (int i = 0; i < map.length; i++) { + System.out.print(i + 1 + " "); + for (int j = 0; j < map.length; j++) { + if (map[i][j] == Cross.NONE){ + String tmp = "┼-"; + if (i == 0) tmp = "┬-"; + if (i == width) tmp = "┴-"; + if (j == 0) tmp = "├-"; + if (j == width) tmp = "┤ "; + + if (i == 0 && j == 0) tmp = "┌-"; + if (i == 0 && j == width) tmp = "┐"; + if (i == width && j == 0) tmp = "└-"; + if (i == width && j == width) tmp = "┘"; + + System.out.print(tmp); + } else if (map[i][j] == Cross.BLACK){ + System.out.print("● "); + } else { + System.out.print("○ "); + } + } + System.out.println(); + } + System.out.print((now == Cross.BLACK ? " [ ● ] " : " [ ○ ] ") + " : "); + } +} + diff --git a/client/src/top/dreamcenter/go/client/DataUtil.java b/client/src/top/dreamcenter/go/client/DataUtil.java new file mode 100644 index 0000000..c1468e5 --- /dev/null +++ b/client/src/top/dreamcenter/go/client/DataUtil.java @@ -0,0 +1,37 @@ +package top.dreamcenter.go.client; + +import top.dreamcenter.go.msg.Cross; + +public class DataUtil { + + public static String parseData(Cross[][] map){ + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map.length; j++) { + sb.append(i).append(j); + if (map[i][j] == Cross.NONE) { + sb.append(0); + } else if (map[i][j] == Cross.BLACK) { + sb.append(1); + } else { + sb.append(2); + } + } + } + return sb.toString(); + } + + public static Cross[][] rawData(String data){ + Cross[][] cross = new Cross[9][9]; + Cross[] colors = new Cross[]{Cross.NONE, Cross.BLACK, Cross.WHITE}; + for (int i = 0; i < data.length(); ) { + int row = data.charAt(i) - '0'; + int col = data.charAt(i + 1) - '0'; + Cross color = colors[data.charAt(i + 2) - '0']; + cross[row][col] = color; + i += 3; + } + + return cross; + } +} diff --git a/client/src/top/dreamcenter/go/client/MainFrame.java b/client/src/top/dreamcenter/go/client/MainFrame.java new file mode 100644 index 0000000..faf8315 --- /dev/null +++ b/client/src/top/dreamcenter/go/client/MainFrame.java @@ -0,0 +1,145 @@ +package top.dreamcenter.go.client; + +import top.dreamcenter.go.msg.Cross; +import top.dreamcenter.go.msg.NewClick; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class MainFrame extends JFrame { + + private static final int BASE_HEIGHT = 26; + private static final int BASE_FROM = 20; + + Cross[][] map = new Cross[9][9]; + Cross now = Cross.NONE; + + public MainFrame(ObjectInputStream oi, ObjectOutputStream os) { + now = (Cross) Client.recMsg(oi); + System.out.println(now); + setTitle(now == Cross.BLACK ? "●" : "○"); + + setSize(200,200 + BASE_HEIGHT); + + addMouseListener(new MouseAdapter() { + @Override + public void mouseReleased(MouseEvent e) { + int x = e.getX() - BASE_FROM; + int y = e.getY() - BASE_FROM - BASE_HEIGHT; + + int col = (x%BASE_FROM < BASE_FROM / 2) ? (x / BASE_FROM) : (x / BASE_FROM + 1); + int row = (y%BASE_FROM < BASE_FROM / 2) ? (y / BASE_FROM) : (y / BASE_FROM + 1); + System.out.printf("[click] row: %d; col: %d;\n", row, col); + + NewClick newClick = NewClick.newInstance(now, row + 1, col + 1); + + Client.sendMsg(os, newClick); + + repaint(); + } + }); + + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setVisible(true); + + new Thread(() -> { + while (true) { + try { + String o = (String) Client.recMsg(oi); + map = DataUtil.rawData(o); + repaint(); + } catch (Exception e){ + e.printStackTrace(); + System.out.println("连接断开"); + break; + } + } + }).start(); + } + + @Override + public void paint(Graphics g) { + g.setColor(Color.white); + g.fillRect(0,BASE_HEIGHT,200,200); + + g.setColor(Color.lightGray); + for (int i = 1; i <= 9; i++) { + drawLine(g, BASE_FROM, BASE_FROM * i, BASE_FROM * 9, BASE_FROM * i); + drawLine(g, BASE_FROM * i, BASE_FROM, BASE_FROM * i, BASE_FROM * 9); + } + + g.setColor(Color.black); + + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map.length; j++) { + if (map[i][j] != Cross.NONE) { + drawDot(g, i+1, j+1, map[i][j]); + } + } + } + } + + @Override + public void update(Graphics g) { + Image tmp = createImage(200, 200); + Graphics tmpG = tmp.getGraphics(); + paint(tmpG); + g.drawImage(tmp, 0,BASE_HEIGHT,null); + } + + /** + * 绘制线 + * @param g g + * @param x1 x1 + * @param y1 y1 + * @param x2 x2 + * @param y2 y2 + */ + private void drawLine(Graphics g, int x1, int y1, int x2, int y2) { + g.drawLine(x1, BASE_HEIGHT + y1, x2, BASE_HEIGHT + y2); + } + + /** + *绘制实心圆 + * @param g g + * @param cx 圆中心点x + * @param cy 圆中心点y + * @param r 半径 + */ + private void fillOval(Graphics g, int cx, int cy, int r) { + g.fillOval(cx - r, cy - r, r<<1, r<<1); + } + + /** + * 绘制空心圆 + * @param g g + * @param cx 圆中心点x + * @param cy 圆中心点y + * @param r 半径 + */ + private void drawOval(Graphics g, int cx, int cy, int r) { + g.drawOval(cx - r, cy - r, r<<1, r<<1); + } + + /** + * 绘制棋子 + * @param g g + * @param row 行 + * @param col 列 + */ + private void drawDot(Graphics g, int row, int col, Cross cross){ + if (cross == Cross.BLACK) { + fillOval(g, col * BASE_FROM , row * BASE_FROM + BASE_HEIGHT, BASE_FROM / 2); + } + if (cross == Cross.WHITE) { + drawOval(g, col * BASE_FROM , row * BASE_FROM + BASE_HEIGHT, BASE_FROM / 2 - 1); + drawOval(g, col * BASE_FROM , row * BASE_FROM + BASE_HEIGHT, BASE_FROM / 2 - 2); + } + } + + +} diff --git a/client/src/top/dreamcenter/go/msg/Cross.java b/client/src/top/dreamcenter/go/msg/Cross.java new file mode 100644 index 0000000..8380627 --- /dev/null +++ b/client/src/top/dreamcenter/go/msg/Cross.java @@ -0,0 +1,5 @@ +package top.dreamcenter.go.msg; + +public enum Cross { + NONE, BLACK, WHITE +} diff --git a/client/src/top/dreamcenter/go/msg/KVPair.java b/client/src/top/dreamcenter/go/msg/KVPair.java new file mode 100644 index 0000000..84121d8 --- /dev/null +++ b/client/src/top/dreamcenter/go/msg/KVPair.java @@ -0,0 +1,16 @@ +package top.dreamcenter.go.msg; + +import java.io.Serializable; + +public class KVPair implements Serializable { + + private static final long serialVersionUID = 19198686; + + public int k; + public int v; + + public KVPair(int k, int v) { + this.k = k; + this.v = v; + } +} diff --git a/client/src/top/dreamcenter/go/msg/NewClick.java b/client/src/top/dreamcenter/go/msg/NewClick.java new file mode 100644 index 0000000..d2cd431 --- /dev/null +++ b/client/src/top/dreamcenter/go/msg/NewClick.java @@ -0,0 +1,20 @@ +package top.dreamcenter.go.msg; + +import java.io.Serializable; + +public class NewClick implements Serializable { + + private static final long serialVersionUID = 19196868; + + public Cross color; + public KVPair pos; + + private NewClick(Cross color, int row, int col) { + this.color = color; + pos = new KVPair(row, col); + } + + public static NewClick newInstance(Cross color, int row, int col) { + return new NewClick(color, row, col); + } +} diff --git a/server/src/META-INF/MANIFEST.MF b/server/src/META-INF/MANIFEST.MF new file mode 100644 index 0000000..7c8d67f --- /dev/null +++ b/server/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: top.dreamcenter.go.server.Server + diff --git a/server/src/top/dreamcenter/go/msg/Cross.java b/server/src/top/dreamcenter/go/msg/Cross.java new file mode 100644 index 0000000..8380627 --- /dev/null +++ b/server/src/top/dreamcenter/go/msg/Cross.java @@ -0,0 +1,5 @@ +package top.dreamcenter.go.msg; + +public enum Cross { + NONE, BLACK, WHITE +} diff --git a/server/src/top/dreamcenter/go/msg/KVPair.java b/server/src/top/dreamcenter/go/msg/KVPair.java new file mode 100644 index 0000000..f19b9cf --- /dev/null +++ b/server/src/top/dreamcenter/go/msg/KVPair.java @@ -0,0 +1,24 @@ +package top.dreamcenter.go.msg; + +import java.io.Serializable; + +public class KVPair implements Serializable { + + private static final long serialVersionUID = 19198686; + + public int k; + public int v; + + public KVPair(int k, int v) { + this.k = k; + this.v = v; + } + + @Override + public String toString() { + return "KVPair{" + + "k=" + k + + ", v=" + v + + '}'; + } +} diff --git a/server/src/top/dreamcenter/go/msg/NewClick.java b/server/src/top/dreamcenter/go/msg/NewClick.java new file mode 100644 index 0000000..9069d58 --- /dev/null +++ b/server/src/top/dreamcenter/go/msg/NewClick.java @@ -0,0 +1,29 @@ +package top.dreamcenter.go.msg; + + +import java.io.Serializable; + +public class NewClick implements Serializable { + + private static final long serialVersionUID = 19196868; + + public Cross color; + public KVPair pos; + + private NewClick(Cross color, int row, int col) { + this.color = color; + pos = new KVPair(row, col); + } + + public static NewClick newInstance(Cross color, int row, int col) { + return new NewClick(color, row, col); + } + + @Override + public String toString() { + return "NewClick{" + + "color=" + color + + ", pos=" + pos + + '}'; + } +} diff --git a/server/src/top/dreamcenter/go/server/CalDataUtil.java b/server/src/top/dreamcenter/go/server/CalDataUtil.java new file mode 100644 index 0000000..f7e6edc --- /dev/null +++ b/server/src/top/dreamcenter/go/server/CalDataUtil.java @@ -0,0 +1,155 @@ +package top.dreamcenter.go.server; + +import top.dreamcenter.go.msg.Cross; +import top.dreamcenter.go.msg.KVPair; +import top.dreamcenter.go.msg.NewClick; + +import java.util.ArrayList; +import java.util.List; + +public class CalDataUtil { + + public static Cross[][] getInitMap() { + Cross[][] map = new Cross[9][9]; + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map.length; j++) { + map[i][j] = Cross.NONE; + } + } + return map; + } + + public static boolean draw(NewClick newClick, Cross[][] map) { + Cross cross = newClick.color; + int row = newClick.pos.k; + int col = newClick.pos.v; + return draw(cross, row, col, map); + } + + public static boolean draw(Cross cross, int row, int col, Cross[][] map) { + int width = map.length; + if (row > width || row < 1 || col > width || col < 1 || (map[row - 1][col - 1] != Cross.NONE && cross != Cross.NONE)) return false; + map[row - 1][col - 1] = cross; + if (cross != Cross.NONE) check(cross, map); + return true; + } + + public static void printMap(Cross[][] map, Cross now){ + System.out.println(); + int width = map.length - 1; + System.out.println("O A B C D E F G H I"); + for (int i = 0; i < map.length; i++) { + System.out.print(i + 1 + " "); + for (int j = 0; j < map.length; j++) { + if (map[i][j] == Cross.NONE){ + String tmp = "┼-"; + if (i == 0) tmp = "┬-"; + if (i == width) tmp = "┴-"; + if (j == 0) tmp = "├-"; + if (j == width) tmp = "┤ "; + + if (i == 0 && j == 0) tmp = "┌-"; + if (i == 0 && j == width) tmp = "┐"; + if (i == width && j == 0) tmp = "└-"; + if (i == width && j == width) tmp = "┘"; + + System.out.print(tmp); + } else if (map[i][j] == Cross.BLACK){ + System.out.print("● "); + } else { + System.out.print("○ "); + } + } + System.out.println(); + } + System.out.print((now == Cross.BLACK ? " [ ● ] " : " [ ○ ] ") + " : "); + } + + /** + * clear dead : BFS + * @param cross cur + * @param map map + */ + private static void check (Cross cross, Cross[][] map) { + int width = map.length - 1; + // 遍历 黑色,出现黑色时,查找边缘,只要存在存在空白则安全。bfs查找 + + Cross obc = cross == Cross.BLACK ? Cross.WHITE : Cross.BLACK; + + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map.length; j++) { + if (map[i][j] == obc) { + // BFS 查找是否存在 NONE 边界 + int len = 0; + List queue = new ArrayList<>(); + queue.add(new KVPair(i, j)); + List colored = new ArrayList<>(); + colored.add(new KVPair(i, j)); + + boolean isDead = true; + while (len < queue.size()) { + // 获取当前的四周,插入到queue + KVPair kvPair = queue.get(len); + int row = kvPair.k; + int col = kvPair.v; + + // 上 + if (kvPair.k != 0 && isAliveOrAdd(colored, map, row - 1, col, obc, queue)) { + isDead = false; + break; + } + + // 下 + if (kvPair.k != width && isAliveOrAdd(colored, map, row + 1, col, obc, queue)) { + isDead = false; + break; + } + + // 左 + if (kvPair.v != 0 && isAliveOrAdd(colored, map, row, col - 1, obc, queue)) { + isDead = false; + break; + } + + // 右 + if (kvPair.v != width && isAliveOrAdd(colored, map, row, col + 1, obc, queue)) { + isDead = false; + break; + } + + len++; + } + + if (isDead) { + // 去除操作 + colored.forEach(item -> draw(Cross.NONE, item.k + 1, item.v + 1, map)); + } + } + } + } + + } + + private static boolean isAliveOrAdd(List colored, Cross[][] map, int row, int col, Cross obc, List queue){ + if (isColored(colored, row, col)) return false; + + // 活的,则退出整个大循环 + if (map[row][col] == Cross.NONE) { + return true; + } + + // 为己方的,则假如队列,否则对方不进行操作 + if (map[row][col] == obc) { + queue.add(new KVPair(row, col)); + colored.add(new KVPair(row, col)); + } + return false; + } + + private static boolean isColored(List colored, int row, int col) { + for (KVPair tmp:colored) { + if (tmp.k == row && tmp.v == col) return true; + } + return false; + } +} diff --git a/server/src/top/dreamcenter/go/server/DataUtil.java b/server/src/top/dreamcenter/go/server/DataUtil.java new file mode 100644 index 0000000..89a7cd4 --- /dev/null +++ b/server/src/top/dreamcenter/go/server/DataUtil.java @@ -0,0 +1,37 @@ +package top.dreamcenter.go.server; + +import top.dreamcenter.go.msg.Cross; + +public class DataUtil { + + public static String parseData(Cross[][] map){ + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < map.length; i++) { + for (int j = 0; j < map.length; j++) { + sb.append(i).append(j); + if (map[i][j] == Cross.NONE) { + sb.append(0); + } else if (map[i][j] == Cross.BLACK) { + sb.append(1); + } else { + sb.append(2); + } + } + } + return sb.toString(); + } + + public static Cross[][] rawData(String data){ + Cross[][] cross = new Cross[9][9]; + Cross[] colors = new Cross[]{Cross.NONE, Cross.BLACK, Cross.WHITE}; + for (int i = 0; i < data.length();) { + int row = data.charAt(i) - '0'; + int col = data.charAt(i + 1) - '0'; + Cross color = colors[data.charAt(i + 2) - '0']; + cross[row][col] = color; + i += 3; + } + + return cross; + } +} diff --git a/server/src/top/dreamcenter/go/server/Server.java b/server/src/top/dreamcenter/go/server/Server.java new file mode 100644 index 0000000..00008e0 --- /dev/null +++ b/server/src/top/dreamcenter/go/server/Server.java @@ -0,0 +1,42 @@ +package top.dreamcenter.go.server; + +import top.dreamcenter.go.msg.Cross; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +public class Server { + public static void main(String[] args) throws IOException { + ServerSocket serverSocket = new ServerSocket(1919); + + while (true) { + AtomicBoolean cur = new AtomicBoolean(true); // true : black ; false : white + + System.out.println("地图初始化 ..."); + Cross[][] map = CalDataUtil.getInitMap(); + System.out.println("初始化完成"); + + + List list = new ArrayList<>(); + + System.out.println("等待用户1接入 ... "); + Socket u1 = serverSocket.accept(); + System.out.println("用户1已连接"); + UserThread u1t = new UserThread(u1, map, cur, Cross.BLACK, list); + u1t.start(); + list.add(u1t); + + System.out.println("等待用户2接入 ... "); + Socket u2 = serverSocket.accept(); + System.out.println("用户2已连接"); + UserThread u2t = new UserThread(u2, map, cur, Cross.WHITE, list); + u2t.start(); + list.add(u2t); + } + } + +} diff --git a/server/src/top/dreamcenter/go/server/UserThread.java b/server/src/top/dreamcenter/go/server/UserThread.java new file mode 100644 index 0000000..86817b7 --- /dev/null +++ b/server/src/top/dreamcenter/go/server/UserThread.java @@ -0,0 +1,105 @@ +package top.dreamcenter.go.server; + +import top.dreamcenter.go.msg.Cross; +import top.dreamcenter.go.msg.NewClick; + +import java.io.IOException; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +public class UserThread extends Thread{ + + private Socket socket; + + private ObjectOutputStream os; + private ObjectInput oi; + + private Cross[][] map; + + private AtomicBoolean cur; + private Cross self; + + private List users; + + public boolean isAlive; + + + public UserThread(Socket socket, Cross[][] map, AtomicBoolean cur, Cross self, List list) { + this.socket = socket; + try { + os = new ObjectOutputStream(socket.getOutputStream()); + oi = new ObjectInputStream(socket.getInputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + this.map = map; + this.cur = cur; + this.self = self; + users = list; + isAlive = true; + } + + @Override + public void run() { + try { + sendMsg(self); + } catch (IOException e) { + e.printStackTrace(); + } + + // 不间断接收消息 + Thread thread = new Thread(() -> { + while (true) { + try { + Object o = recMsg(); + NewClick newClick = (NewClick) o; + + if (newClick.color == (cur.get() ? Cross.BLACK : Cross.WHITE) && newClick.color == self){ + CalDataUtil.draw(newClick, map); + cur.set(!cur.get()); + } + + users.forEach(u -> { + try { + if (u.isAlive) u.sendMsg(DataUtil.parseData(map)); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } catch (Exception e){ + System.out.println("::" + e.getMessage()); + System.out.println("连接断开"); + isAlive = false; + break; + } + } + }); + thread.start(); + + // 线程等待 + try { + thread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } + + public Socket getSocket() { + return socket; + } + + public void sendMsg(Object obj) throws IOException { + os.writeObject(obj); + } + + private Object recMsg() throws IOException, ClassNotFoundException { + return oi.readObject(); + } +}