diff --git a/pom.xml b/pom.xml
index 5ed1bec..b172fed 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,16 +7,28 @@
1.0-SNAPSHOT
jar
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.3
+
+
+
Tcp-Server
http://maven.apache.org
UTF-8
- 21
+ 1.8
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
cn.hutool
hutool-all
@@ -36,8 +48,8 @@
org.apache.maven.plugins
maven-compiler-plugin
- 21
- 21
+ 1.8
+ 1.8
diff --git a/src/main/java/com/zhangmeng/Constant.java b/src/main/java/com/zhangmeng/Constant.java
new file mode 100644
index 0000000..0d7359f
--- /dev/null
+++ b/src/main/java/com/zhangmeng/Constant.java
@@ -0,0 +1,9 @@
+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 4772d21..28f9dcb 100644
--- a/src/main/java/com/zhangmeng/TcpApplication.java
+++ b/src/main/java/com/zhangmeng/TcpApplication.java
@@ -1,24 +1,30 @@
package com.zhangmeng;
import com.zhangmeng.service.impl.ServerImpl;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Hello world!
- *
*/
-public class TcpApplication
-{
- public static void main( String[] args )
- {
-
- ServerImpl.Config config = new ServerImpl.Config();
- config.setName("SimpleServer");
- config.setIPVersion("IPv4");
- config.setIP("127.0.0.1");
- config.setPort(8888);
- ServerImpl server = new ServerImpl();
- server.setConfig(config);
- server.Start();
+@SpringBootApplication
+public class TcpApplication {
+ public static void main(String[] args) {
+ new TcpServer().start();
+ SpringApplication.run(TcpApplication.class, args);
+ }
+ public static class TcpServer extends Thread {
+ @Override
+ public void run() {
+ ServerImpl.Config config = new ServerImpl.Config();
+ config.setName("SimpleServer");
+ config.setIPVersion("IPv4");
+ config.setIP("127.0.0.1");
+ config.setPort(9999);
+ ServerImpl server = new ServerImpl();
+ server.setConfig(config);
+ server.Start();
+ }
}
}
diff --git a/src/main/java/com/zhangmeng/callBack/HandlerApiCallBack.java b/src/main/java/com/zhangmeng/callBack/HandlerApiCallBack.java
new file mode 100644
index 0000000..22f44db
--- /dev/null
+++ b/src/main/java/com/zhangmeng/callBack/HandlerApiCallBack.java
@@ -0,0 +1,18 @@
+package com.zhangmeng.callBack;
+
+import com.zhangmeng.handler.HandlerApi;
+
+import java.net.Socket;
+
+/**
+ * @author zm
+ * @date 2025/2/22 11:54
+ * @version: 1.0
+ */
+public class HandlerApiCallBack implements HandlerApi {
+
+ @Override
+ public void handle(Socket socket, byte[] data) {
+ System.out.println("HandlerApiCallBack handle data:" + new String(data));
+ }
+}
diff --git a/src/main/java/com/zhangmeng/controller/TcpSocketController.java b/src/main/java/com/zhangmeng/controller/TcpSocketController.java
new file mode 100644
index 0000000..daf485a
--- /dev/null
+++ b/src/main/java/com/zhangmeng/controller/TcpSocketController.java
@@ -0,0 +1,34 @@
+package com.zhangmeng.controller;
+
+import com.zhangmeng.service.impl.ServerImpl;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.net.Socket;
+
+/**
+ * @author zm
+ * @date 2025/2/22 11:11
+ * @version: 1.0
+ */
+@RestController
+@RequestMapping("/tcpSocket")
+public class TcpSocketController {
+
+ @RequestMapping("/send")
+ public void send(String message,String key){
+ Socket socket = ServerImpl.socketList.get(key);
+ if(socket!= null){
+ try {
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
+ writer.write(message);
+ writer.flush();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/zhangmeng/handler/ClientHandler.java b/src/main/java/com/zhangmeng/handler/ClientHandler.java
index 3e7d6a0..48b2f7b 100644
--- a/src/main/java/com/zhangmeng/handler/ClientHandler.java
+++ b/src/main/java/com/zhangmeng/handler/ClientHandler.java
@@ -1,6 +1,8 @@
package com.zhangmeng.handler;
import cn.hutool.core.io.BufferUtil;
+import cn.hutool.log.Log;
+import cn.hutool.log.LogFactory;
import java.io.*;
import java.net.Socket;
@@ -10,14 +12,18 @@ import java.net.Socket;
* @date 2025/2/21 15:40
* @version: 1.0
*/
-public class ClientHandler implements Runnable {
+public class ClientHandler extends Thread {
+
+ private final Log log = LogFactory.get();
private Socket socket;
- // private BufferedReader reader;
-// private BufferedWriter writer;
+ private BufferedReader reader;
+ private BufferedWriter writer;
private OutputStream outputStream;
private InputStream inputStream;
+ public boolean canRun = true;
+
public void close() {
try {
outputStream.close();
@@ -30,21 +36,21 @@ public class ClientHandler implements Runnable {
@Override
public void run() {
- while (true) {
- try {
- byte[] bytes = new byte[1024];
- int len = inputStream.read(bytes);
- if (len == -1) {
- break;
- }
- String message = new String(bytes, 0, len);
- System.out.println("receive message: " + message);
-
-
- } catch (IOException e) {
- throw new RuntimeException(e);
+ try {
+ while (true) {
+ // main 线程负责读取客户端发来的信息
+ String str = reader.readLine();
+ log.info("客户端说:" + str);
+ // main 线程负责读取客户端发来的信息
+ writer.write("服务器收到消息:" + "\n");
+ writer.flush();
}
+
+ } catch (IOException e) {
+ close();
+ //throw new RuntimeException(e);
}
+
}
public Socket getSocket() {
@@ -60,8 +66,43 @@ public class ClientHandler implements Runnable {
try {
this.inputStream = socket.getInputStream();
this.outputStream = socket.getOutputStream();
+ this.reader = new BufferedReader(new InputStreamReader(inputStream));
+// this.reader = new BufferedReader(new InputStreamReader(System.in));
+ this.writer = new BufferedWriter(new OutputStreamWriter(outputStream));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
+
+ public BufferedReader getReader() {
+ return reader;
+ }
+
+ public void setReader(BufferedReader reader) {
+ this.reader = reader;
+ }
+
+ public BufferedWriter getWriter() {
+ return writer;
+ }
+
+ public void setWriter(BufferedWriter writer) {
+ this.writer = writer;
+ }
+
+ public OutputStream getOutputStream() {
+ return outputStream;
+ }
+
+ public void setOutputStream(OutputStream outputStream) {
+ this.outputStream = outputStream;
+ }
+
+ public InputStream getInputStream() {
+ return inputStream;
+ }
+
+ public void setInputStream(InputStream inputStream) {
+ this.inputStream = inputStream;
+ }
}
diff --git a/src/main/java/com/zhangmeng/handler/HandlerApi.java b/src/main/java/com/zhangmeng/handler/HandlerApi.java
new file mode 100644
index 0000000..01a3481
--- /dev/null
+++ b/src/main/java/com/zhangmeng/handler/HandlerApi.java
@@ -0,0 +1,14 @@
+package com.zhangmeng.handler;
+
+import java.net.Socket;
+
+/**
+ * @author zm
+ * @date 2025/2/22 11:53
+ * @version: 1.0
+ */
+public interface HandlerApi {
+
+ void handle(Socket socket,byte[] data);
+
+}
diff --git a/src/main/java/com/zhangmeng/service/Connection.java b/src/main/java/com/zhangmeng/service/Connection.java
new file mode 100644
index 0000000..7071982
--- /dev/null
+++ b/src/main/java/com/zhangmeng/service/Connection.java
@@ -0,0 +1,28 @@
+package com.zhangmeng.service;
+
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * @author zm
+ * @date 2025/2/22 11:41
+ * @version: 1.0
+ */
+public interface Connection {
+
+
+ //启动连接,让当前连接开始工作
+ public void Start();
+
+ //停止连接,结束当前连接状态M
+ public void Stop();
+
+ //从当前连接获取原始的socket TCPConn
+ public Socket GetTCPConnection();
+
+ //获取当前连接ID
+ public int GetConnID();
+
+ //获取远程客户端地址信息
+ public InetAddress RemoteAddr();
+}
diff --git a/src/main/java/com/zhangmeng/service/impl/ConnectionImpl.java b/src/main/java/com/zhangmeng/service/impl/ConnectionImpl.java
new file mode 100644
index 0000000..4e6b2ef
--- /dev/null
+++ b/src/main/java/com/zhangmeng/service/impl/ConnectionImpl.java
@@ -0,0 +1,166 @@
+package com.zhangmeng.service.impl;
+
+import cn.hutool.log.Log;
+import cn.hutool.log.LogFactory;
+import com.zhangmeng.handler.HandlerApi;
+import com.zhangmeng.service.Connection;
+
+import java.io.*;
+import java.net.InetAddress;
+import java.net.Socket;
+
+/**
+ * @author zm
+ * @date 2025/2/22 11:41
+ * @version: 1.0
+ */
+public class ConnectionImpl implements Connection {
+
+ private final Log log = LogFactory.get();
+
+ //当前连接的socket TCP套接字
+ private Socket Conn;
+ //当前连接的ID 也可以称作为SessionID,ID全局唯一
+ private int ConnID;
+ //当前连接的关闭状态
+ private boolean isClosed;
+
+ //该连接的处理方法api
+ private HandlerApi handleAPI;
+
+ //告知该链接已经退出/停止的channel
+ boolean ExitBuffChan;
+
+ private BufferedReader reader;
+ private BufferedWriter writer;
+ private OutputStream outputStream;
+ private InputStream inputStream;
+
+
+ //创建连接的方法
+ public ConnectionImpl(Socket conn, int connID, HandlerApi callback_api) {
+ this.Conn = conn;
+ this.ConnID = connID;
+ this.isClosed = false;
+ this.handleAPI = callback_api;
+ this.ExitBuffChan = false;
+
+ try {
+ this.inputStream = conn.getInputStream();
+ this.outputStream = conn.getOutputStream();
+ this.reader = new BufferedReader(new InputStreamReader(inputStream));
+// this.reader = new BufferedReader(new InputStreamReader(System.in));
+ this.writer = new BufferedWriter(new OutputStreamWriter(outputStream));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void close() {
+ try {
+ reader.close();
+ writer.close();
+ outputStream.close();
+ inputStream.close();
+ Conn.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ //处理conn读数据的Goroutine
+ public void StartReader() {
+ log.info("Reader Goroutine is running");
+ boolean exit = true;
+ while (exit) {
+ //读取我们最大的数据到buf中
+ try {
+ String str = reader.readLine();
+ //调用当前链接业务(这里执行的是当前conn的绑定的handle方法)
+ this.handleAPI.handle(this.Conn, str.getBytes());
+// log.info("recv buf : " + str);
+ writer.write(str + "\n");
+ writer.flush();
+
+ } catch (IOException e) {
+// throw new RuntimeException(e);
+ log.error("recv buf err ", e.getMessage());
+ //退出循环
+ exit = false;
+ this.ExitBuffChan = true;
+ this.Stop();
+ }
+ }
+
+ }
+
+
+ @Override
+ public void Start() {
+ log.info("Start ConnectionImpl ..............................................");
+ StartReader();
+ }
+
+ @Override
+ public void Stop() {
+ log.info("Stop ConnectionImpl ..............................................");
+ //关闭当前连接
+ this.close();
+ }
+
+ @Override
+ public Socket GetTCPConnection() {
+ return null;
+ }
+
+ @Override
+ public int GetConnID() {
+ return 0;
+ }
+
+ @Override
+ public InetAddress RemoteAddr() {
+ return null;
+ }
+
+
+ public Socket getConn() {
+ return Conn;
+ }
+
+ public void setConn(Socket conn) {
+ Conn = conn;
+ }
+
+ public int getConnID() {
+ return ConnID;
+ }
+
+ public void setConnID(int connID) {
+ ConnID = connID;
+ }
+
+ public boolean isClosed() {
+ return isClosed;
+ }
+
+ public void setClosed(boolean closed) {
+ isClosed = closed;
+ }
+
+ public HandlerApi getHandleAPI() {
+ return handleAPI;
+ }
+
+ public void setHandleAPI(HandlerApi handleAPI) {
+ this.handleAPI = handleAPI;
+ }
+
+ public boolean isExitBuffChan() {
+ return ExitBuffChan;
+ }
+
+ public void setExitBuffChan(boolean exitBuffChan) {
+ ExitBuffChan = exitBuffChan;
+ }
+}
diff --git a/src/main/java/com/zhangmeng/service/impl/ServerImpl.java b/src/main/java/com/zhangmeng/service/impl/ServerImpl.java
index 59d8a24..4a1f043 100644
--- a/src/main/java/com/zhangmeng/service/impl/ServerImpl.java
+++ b/src/main/java/com/zhangmeng/service/impl/ServerImpl.java
@@ -9,7 +9,9 @@ import cn.hutool.log.StaticLog;
import cn.hutool.socket.aio.AioServer;
import cn.hutool.socket.aio.AioSession;
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.Server;
import java.io.*;
@@ -18,6 +20,11 @@ import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* @author zm
@@ -32,20 +39,33 @@ public class ServerImpl implements Server {
private ServerSocket serverSocket;
+ private BufferedReader in;
+
+ public static Map socketList = new HashMap<>();
+
@Override
public void Start() {
log.info("[START] Server listenner at IP: {}, Port {}, is starting", config.getIP(), config.getPort());
try {
serverSocket = new ServerSocket(config.getPort());
+ int cid = 0;
+
while (true) {
Socket accept = serverSocket.accept();
+ String key = accept.getInetAddress().getHostAddress() + ":" + accept.getPort();
+ socketList.put(key, accept);
+ log.info("key=====================================: " + key);
+ //new ClientHandler(accept).start();
log.info("[ACCEPT] Accept a client at IP: {}, Port {}", accept.getInetAddress().getHostAddress(), accept.getPort());
- new Thread(new ClientHandler(accept)).start();
+ Connection conn = new ConnectionImpl(accept,cid,new HandlerApiCallBack());
+ conn.Start();
+ cid++;
}
} catch (IOException e) {
- throw new RuntimeException(e);
+// throw new RuntimeException(e);
+ log.error(e.getMessage());
}
}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
new file mode 100644
index 0000000..47fbb02
--- /dev/null
+++ b/src/main/resources/application.yml
@@ -0,0 +1,2 @@
+server:
+ port: 8080
\ No newline at end of file
diff --git a/src/test/java/com/zhangmeng/AppTest.java b/src/test/java/com/zhangmeng/AppTest.java
index be597b1..d52ddae 100644
--- a/src/test/java/com/zhangmeng/AppTest.java
+++ b/src/test/java/com/zhangmeng/AppTest.java
@@ -1,9 +1,9 @@
package com.zhangmeng;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.*;
+import java.net.InetAddress;
import java.net.Socket;
+import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
@@ -14,25 +14,64 @@ import java.util.Scanner;
public class AppTest {
public static void main(String[] args) throws IOException {
- Scanner scanner = new Scanner(System.in);
- System.out.println("等待连接服务端!");
- Socket socket = new Socket("127.0.0.1", 8888);
- System.out.println("连接服务端成功!");
- while (true) {
- // 给服务端发信息
- System.out.print("请输入:");
- String s = scanner.next();
- if ("out".equals(s)) {
- break;
+ 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());
+ }
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } 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();
+ }
}
- OutputStream outputStream = socket.getOutputStream();
- outputStream.write(s.getBytes(StandardCharsets.UTF_8));
- byte[] bytes = new byte[1024];
-
- // 读一下服务端发来的信息
- InputStream inputStream = socket.getInputStream();
- int read = inputStream.read(bytes);
- System.out.println("服务端:" + new String(bytes, 0, read, Charset.defaultCharset()));
}
}