diff --git a/src/main/java/com/zhangmeng/Constant.java b/src/main/java/com/zhangmeng/Constant.java deleted file mode 100644 index 0d7359f..0000000 --- a/src/main/java/com/zhangmeng/Constant.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.zhangmeng; - -/** - * @author zm - * @date 2025/2/22 11:12 - * @version: 1.0 - */ -public class Constant { -} diff --git a/src/main/java/com/zhangmeng/TcpApplication.java b/src/main/java/com/zhangmeng/TcpApplication.java index 28f9dcb..aa1389c 100644 --- a/src/main/java/com/zhangmeng/TcpApplication.java +++ b/src/main/java/com/zhangmeng/TcpApplication.java @@ -1,5 +1,6 @@ package com.zhangmeng; +import com.zhangmeng.service.impl.PingRouter; import com.zhangmeng.service.impl.ServerImpl; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -24,6 +25,7 @@ public class TcpApplication { config.setPort(9999); ServerImpl server = new ServerImpl(); server.setConfig(config); + server.AddRouter(new PingRouter()); server.Start(); } } diff --git a/src/main/java/com/zhangmeng/callBack/HandlerApiCallBack.java b/src/main/java/com/zhangmeng/callBack/HandlerApiCallBack.java index 22f44db..bea3797 100644 --- a/src/main/java/com/zhangmeng/callBack/HandlerApiCallBack.java +++ b/src/main/java/com/zhangmeng/callBack/HandlerApiCallBack.java @@ -1,7 +1,11 @@ package com.zhangmeng.callBack; +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; import com.zhangmeng.handler.HandlerApi; +import java.io.BufferedWriter; +import java.io.IOException; import java.net.Socket; /** @@ -11,8 +15,16 @@ import java.net.Socket; */ public class HandlerApiCallBack implements HandlerApi { + private final Log log = LogFactory.get(); + @Override - public void handle(Socket socket, byte[] data) { - System.out.println("HandlerApiCallBack handle data:" + new String(data)); + public void handle(BufferedWriter writer, byte[] data) { + log.info("HandlerApiCallBack handle data:" + new String(data)); + try { + writer.write(new String(data)); + writer.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/com/zhangmeng/handler/HandlerApi.java b/src/main/java/com/zhangmeng/handler/HandlerApi.java index 01a3481..910675f 100644 --- a/src/main/java/com/zhangmeng/handler/HandlerApi.java +++ b/src/main/java/com/zhangmeng/handler/HandlerApi.java @@ -1,5 +1,6 @@ package com.zhangmeng.handler; +import java.io.BufferedWriter; import java.net.Socket; /** @@ -9,6 +10,6 @@ import java.net.Socket; */ public interface HandlerApi { - void handle(Socket socket,byte[] data); + void handle(BufferedWriter writer, byte[] data); } diff --git a/src/main/java/com/zhangmeng/service/Request.java b/src/main/java/com/zhangmeng/service/Request.java new file mode 100644 index 0000000..eef7e1f --- /dev/null +++ b/src/main/java/com/zhangmeng/service/Request.java @@ -0,0 +1,14 @@ +package com.zhangmeng.service; + +/** + * @author zm + * @date 2025/2/22 15:45 + * @version: 1.0 + */ +public interface Request { + + public Connection GetConnection(); //获取请求连接信息 + + public byte[] GetData(); //获取请求消息的数据 + +} diff --git a/src/main/java/com/zhangmeng/service/Router.java b/src/main/java/com/zhangmeng/service/Router.java new file mode 100644 index 0000000..f4c75fd --- /dev/null +++ b/src/main/java/com/zhangmeng/service/Router.java @@ -0,0 +1,19 @@ +package com.zhangmeng.service; + +/** + * 路由接口, 这里面路由是 使用框架者给该链接自定的 处理业务方法 + * 路由里的IRequest 则包含用该链接的链接信息和该链接的请求数据信息 + * + * @author zm + * @date 2025/2/22 15:48 + * @version: 1.0 + */ +public interface Router { + + public void PreHandle(Request request); //在处理conn业务之前的钩子方法 + + public void Handle(Request request); //处理conn业务的方法 + + public void PostHandle(Request request); //处理conn业务之后的钩子方法 + +} diff --git a/src/main/java/com/zhangmeng/service/Server.java b/src/main/java/com/zhangmeng/service/Server.java index 13c7bee..cf20230 100644 --- a/src/main/java/com/zhangmeng/service/Server.java +++ b/src/main/java/com/zhangmeng/service/Server.java @@ -17,5 +17,6 @@ public interface Server { //开启业务服务方法 public void Serve(); - + //路由功能:给当前服务注册一个路由业务方法,供客户端链接处理使用 + public void AddRouter( Router router); } diff --git a/src/main/java/com/zhangmeng/service/impl/BaseRouterImpl.java b/src/main/java/com/zhangmeng/service/impl/BaseRouterImpl.java new file mode 100644 index 0000000..ae28215 --- /dev/null +++ b/src/main/java/com/zhangmeng/service/impl/BaseRouterImpl.java @@ -0,0 +1,31 @@ +package com.zhangmeng.service.impl; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.zhangmeng.service.Request; +import com.zhangmeng.service.Router; + +/** + * @author zm + * @date 2025/2/22 15:51 + * @version: 1.0 + */ +public class BaseRouterImpl implements Router { + + private final Log log = LogFactory.get(); + + @Override + public void PreHandle(Request request) { + log.info("PreHandle ======================================"); + } + + @Override + public void Handle(Request request) { + log.info("Handle ======================================"); + } + + @Override + public void PostHandle(Request request) { + log.info("PostHandle ======================================"); + } +} diff --git a/src/main/java/com/zhangmeng/service/impl/ConnectionImpl.java b/src/main/java/com/zhangmeng/service/impl/ConnectionImpl.java index 4e6b2ef..80ee298 100644 --- a/src/main/java/com/zhangmeng/service/impl/ConnectionImpl.java +++ b/src/main/java/com/zhangmeng/service/impl/ConnectionImpl.java @@ -4,6 +4,8 @@ import cn.hutool.log.Log; import cn.hutool.log.LogFactory; import com.zhangmeng.handler.HandlerApi; import com.zhangmeng.service.Connection; +import com.zhangmeng.service.Request; +import com.zhangmeng.service.Router; import java.io.*; import java.net.InetAddress; @@ -31,6 +33,9 @@ public class ConnectionImpl implements Connection { //告知该链接已经退出/停止的channel boolean ExitBuffChan; + //该连接的处理方法router + private Router router; + private BufferedReader reader; private BufferedWriter writer; private OutputStream outputStream; @@ -38,12 +43,13 @@ public class ConnectionImpl implements Connection { //创建连接的方法 - public ConnectionImpl(Socket conn, int connID, HandlerApi callback_api) { + public ConnectionImpl(Socket conn, int connID, Router router) { this.Conn = conn; this.ConnID = connID; this.isClosed = false; - this.handleAPI = callback_api; +// this.handleAPI = callback_api; this.ExitBuffChan = false; + this.router = router; try { this.inputStream = conn.getInputStream(); @@ -77,9 +83,17 @@ public class ConnectionImpl implements Connection { try { String str = reader.readLine(); //调用当前链接业务(这里执行的是当前conn的绑定的handle方法) - this.handleAPI.handle(this.Conn, str.getBytes()); +// this.handleAPI.handle(this.writer, str.getBytes()); + + //构建request对象,并调用router的PreHandle,Handle,PostHandle方法 + Request request = new RequestImpl(this, str.getBytes()); + + this.router.PreHandle(request); + this.router.Handle(request); + this.router.PostHandle(request); + // log.info("recv buf : " + str); - writer.write(str + "\n"); + writer.write("\n"); writer.flush(); } catch (IOException e) { @@ -110,17 +124,17 @@ public class ConnectionImpl implements Connection { @Override public Socket GetTCPConnection() { - return null; + return this.Conn; } @Override public int GetConnID() { - return 0; + return this.ConnID; } @Override public InetAddress RemoteAddr() { - return null; + return this.Conn.getInetAddress(); } diff --git a/src/main/java/com/zhangmeng/service/impl/PingRouter.java b/src/main/java/com/zhangmeng/service/impl/PingRouter.java new file mode 100644 index 0000000..6d07c2f --- /dev/null +++ b/src/main/java/com/zhangmeng/service/impl/PingRouter.java @@ -0,0 +1,63 @@ +package com.zhangmeng.service.impl; + +import cn.hutool.log.Log; +import cn.hutool.log.LogFactory; +import com.zhangmeng.service.Request; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; + +/** + * @author zm + * @date 2025/2/22 16:13 + * @version: 1.0 + */ +public class PingRouter extends BaseRouterImpl { + + private final Log log = LogFactory.get(); + + @Override + public void PreHandle(Request request) { + log.info("Call Router PreHandle"); + Socket socket = request.GetConnection().GetTCPConnection(); + + try { + OutputStream outputStream = socket.getOutputStream(); + outputStream.write("before ping ....".getBytes()); + outputStream.flush(); + } catch (IOException e) { +// throw new RuntimeException(e); + log.error("call back ping ping ping error"); + } + + } + + @Override + public void Handle(Request request) { + log.info("Call Router Handle"); + Socket socket = request.GetConnection().GetTCPConnection(); + try { + OutputStream outputStream = socket.getOutputStream(); + outputStream.write(" ping ....".getBytes()); + outputStream.flush(); + } catch (IOException e) { +// throw new RuntimeException(e); + log.error("call back ping ping ping error"); + } + } + + @Override + public void PostHandle(Request request) { + log.info("Call Router PostHandle"); + Socket socket = request.GetConnection().GetTCPConnection(); + try { + OutputStream outputStream = socket.getOutputStream(); + outputStream.write("after ping ....".getBytes()); + outputStream.flush(); + } catch (IOException e) { +// throw new RuntimeException(e); + log.error("call back ping ping ping error"); + } + } +} diff --git a/src/main/java/com/zhangmeng/service/impl/RequestImpl.java b/src/main/java/com/zhangmeng/service/impl/RequestImpl.java new file mode 100644 index 0000000..ebd6d77 --- /dev/null +++ b/src/main/java/com/zhangmeng/service/impl/RequestImpl.java @@ -0,0 +1,31 @@ +package com.zhangmeng.service.impl; + +import com.zhangmeng.service.Connection; +import com.zhangmeng.service.Request; + +/** + * @author zm + * @date 2025/2/22 15:46 + * @version: 1.0 + */ +public class RequestImpl implements Request { + + private Connection connection; + + private byte[] data; + + public RequestImpl(Connection connection, byte[] data) { + this.connection = connection; + this.data = data; + } + + @Override + public Connection GetConnection() { + return this.connection; + } + + @Override + public byte[] GetData() { + return this.data; + } +} diff --git a/src/main/java/com/zhangmeng/service/impl/ServerImpl.java b/src/main/java/com/zhangmeng/service/impl/ServerImpl.java index 4a1f043..b525bc4 100644 --- a/src/main/java/com/zhangmeng/service/impl/ServerImpl.java +++ b/src/main/java/com/zhangmeng/service/impl/ServerImpl.java @@ -12,6 +12,7 @@ import cn.hutool.socket.aio.SimpleIoAction; import com.zhangmeng.callBack.HandlerApiCallBack; import com.zhangmeng.handler.ClientHandler; import com.zhangmeng.service.Connection; +import com.zhangmeng.service.Router; import com.zhangmeng.service.Server; import java.io.*; @@ -41,6 +42,8 @@ public class ServerImpl implements Server { private BufferedReader in; + private Router router; //当前Server由用户绑定的回调router,也就是Server注册的链接对应的处理业务 + public static Map socketList = new HashMap<>(); @Override @@ -58,7 +61,7 @@ public class ServerImpl implements Server { log.info("key=====================================: " + key); //new ClientHandler(accept).start(); log.info("[ACCEPT] Accept a client at IP: {}, Port {}", accept.getInetAddress().getHostAddress(), accept.getPort()); - Connection conn = new ConnectionImpl(accept,cid,new HandlerApiCallBack()); + Connection conn = new ConnectionImpl(accept,cid,this.router); conn.Start(); cid++; } @@ -84,6 +87,12 @@ public class ServerImpl implements Server { } + @Override + public void AddRouter(Router router) { + this.router = router; + log.info("[ADD ROUTER] Add a router to server"); + } + public void setConfig(Config config) { this.config = config; } @@ -132,4 +141,14 @@ public class ServerImpl implements Server { Port = port; } } + + public Router getRouter() { + return router; + } + + public void setRouter(Router router) { + this.router = router; + } + + } diff --git a/src/test/java/com/zhangmeng/AppTest.java b/src/test/java/com/zhangmeng/AppTest.java index d52ddae..59ff245 100644 --- a/src/test/java/com/zhangmeng/AppTest.java +++ b/src/test/java/com/zhangmeng/AppTest.java @@ -37,12 +37,13 @@ public class AppTest { } //否则,接收并输出服务器端信息 System.out.println("服务器端说:" + in.readLine()); +// Thread.sleep(1000); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); - } finally { + } finally { // 关闭资源 if(out != null) { try { diff --git a/src/test/java/com/zhangmeng/AppTest2.java b/src/test/java/com/zhangmeng/AppTest2.java new file mode 100644 index 0000000..d409219 --- /dev/null +++ b/src/test/java/com/zhangmeng/AppTest2.java @@ -0,0 +1,79 @@ +package com.zhangmeng; + +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author zm + * @date 2025/2/22 15:43 + * @version: 1.0 + */ +public class AppTest2 { + + public static void main(String[] args) { + Socket socket = null; + BufferedReader in = null; + BufferedWriter out = null; + BufferedReader br = null; + try { + //创建 Socket 对象,指定服务器端的 IP 与端口 + socket = new Socket(InetAddress.getLocalHost(), 9999); + //获取 scoket 的输入输出流接收和发送信息 + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new BufferedWriter(new + OutputStreamWriter(socket.getOutputStream())); + br = new BufferedReader(new InputStreamReader(System.in)); + while (true) { + //发送信息 + String str = "br.readLine()"; + out.write(str + "\n"); + out.flush(); + //如果输入的信息为“end”则终止连接 + if (str.equals("end")) { + break; + } + //否则,接收并输出服务器端信息 + System.out.println("服务器端说:" + in.readLine()); + Thread.sleep(1000); + } + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + // 关闭资源 + if(out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(in != null) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(br != null) { + try { + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(socket != null) { + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/src/test/java/com/zhangmeng/AppTest3.java b/src/test/java/com/zhangmeng/AppTest3.java new file mode 100644 index 0000000..d912728 --- /dev/null +++ b/src/test/java/com/zhangmeng/AppTest3.java @@ -0,0 +1,79 @@ +package com.zhangmeng; + +import java.io.*; +import java.net.InetAddress; +import java.net.Socket; +import java.net.UnknownHostException; + +/** + * @author zm + * @date 2025/2/22 15:43 + * @version: 1.0 + */ +public class AppTest3 { + + public static void main(String[] args) { + Socket socket = null; + BufferedReader in = null; + BufferedWriter out = null; + BufferedReader br = null; + try { + //创建 Socket 对象,指定服务器端的 IP 与端口 + socket = new Socket(InetAddress.getLocalHost(), 9999); + //获取 scoket 的输入输出流接收和发送信息 + in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + out = new BufferedWriter(new + OutputStreamWriter(socket.getOutputStream())); + br = new BufferedReader(new InputStreamReader(System.in)); + while (true) { + //发送信息 + String str = "br.readLine()"; + out.write(str + "\n"); + out.flush(); + //如果输入的信息为“end”则终止连接 + if (str.equals("end")) { + break; + } + //否则,接收并输出服务器端信息 + System.out.println("服务器端说:" + in.readLine()); + Thread.sleep(1000); + } + } catch (UnknownHostException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + // 关闭资源 + if(out != null) { + try { + out.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(in != null) { + try { + in.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(br != null) { + try { + br.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + if(socket != null) { + try { + socket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } +}