2025年2月22日15:38:46

master
qmstyle 2025-02-22 15:38:53 +08:00
parent 6b872416ae
commit 1fb7180327
12 changed files with 445 additions and 56 deletions

18
pom.xml
View File

@ -7,16 +7,28 @@
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<name>Tcp-Server</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>21</java.version>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
@ -36,8 +48,8 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>

View File

@ -0,0 +1,9 @@
package com.zhangmeng;
/**
* @author zm
* @date 2025/2/22 11:12
* @version: 1.0
*/
public class Constant {
}

View File

@ -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 )
{
@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(8888);
config.setPort(9999);
ServerImpl server = new ServerImpl();
server.setConfig(config);
server.Start();
}
}
}

View File

@ -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));
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
while (true) {
// main 线程负责读取客户端发来的信息
String str = reader.readLine();
log.info("客户端说:" + str);
// main 线程负责读取客户端发来的信息
writer.write("服务器收到消息:" + "\n");
writer.flush();
}
String message = new String(bytes, 0, len);
System.out.println("receive message: " + message);
} catch (IOException e) {
throw new RuntimeException(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;
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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 也可以称作为SessionIDID全局唯一
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;
}
}

View File

@ -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<String, Socket> 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());
}
}

View File

@ -0,0 +1,2 @@
server:
port: 8080

View File

@ -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("连接服务端成功!");
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) {
// 给服务端发信息
System.out.print("请输入:");
String s = scanner.next();
if ("out".equals(s)) {
//发送信息
String str = br.readLine();
out.write(str + "\n");
out.flush();
//如果输入的信息为“end”则终止连接
if (str.equals("end")) {
break;
}
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()));
//否则,接收并输出服务器端信息
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();
}
}
}
}