Compare commits

..

2 Commits

Author SHA1 Message Date
f2318bccf8
no message
All checks were successful
Gitea Actions Build / Build (push) Successful in 50s
2025-07-05 20:26:23 +08:00
5d1e8871b4
no message 2025-07-05 20:25:17 +08:00
8 changed files with 361 additions and 40 deletions

View File

@ -38,6 +38,8 @@ dependencies {
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation("org.jetbrains:annotations:24.0.0")
annotationProcessor("org.jetbrains:annotations:24.0.0")
implementation("com.mingliqiye:network-endpoint:1.0.2")
implementation("com.mingliqiye:string-utilts:1.0.4")
}
tasks.test {

View File

@ -1,13 +0,0 @@
package com.mingliqiye;
public class Main {
/**
* @param args []
*/
public static void main(String[] args) {
System.out.print("Hello and welcome!");
for (int i = 1; i <= 5; i++) {
System.out.println("i = " + i);
}
}
}

View File

@ -0,0 +1,35 @@
package com.mingliqiye.utils;
public class BufferBytesEntity {
/**
* 数据
*/
private final byte[] bytes;
/**
* 数据大小
*/
private final int len;
/**
* 缓存区大小
*/
private final int buffer;
public BufferBytesEntity(byte[] bytes, int len, int buffer) {
this.bytes = bytes;
this.len = len;
this.buffer = buffer;
}
public byte[] getBytes() {
return bytes;
}
public int getLen() {
return len;
}
public int getBuffer() {
return buffer;
}
}

View File

@ -0,0 +1,63 @@
package com.mingliqiye.utils;
import com.mingliqiye.network.endpoint.NetworkEndpoint;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
public class DefTcpServerImplementation extends TcpServerImplementation {
boolean connect(TcpSocketClient client, String id) {
System.out.println(
StringUtil.format(
"客户端 {} ID={} 连接成功",
client.getEndpoint().toHostPortString(),
id
)
);
return true;
}
void disconnect(TcpSocketClient client, String id) {
System.out.println(
StringUtil.format(
"客户端 {} ID={} 断开连接",
client.getEndpoint().toHostPortString(),
id
)
);
}
void reception(
TcpSocketClient client,
BufferBytesEntity bufferBytesEntity
) {
System.out.println(
StringUtil.format(
"来自客户端 {} ID:{} 的数据 大小:{}",
client.getEndpoint().toHostPortString(),
client.getIds(),
bufferBytesEntity.getLen()
)
);
client.send(
bufferBytesEntity.getBytes(),
0,
bufferBytesEntity.getLen()
);
}
void started(ServerSocket serverSocket) {
System.out.println(
StringUtil.format(
"服务器启动 监听 {}",
NetworkEndpoint.of(
(InetSocketAddress) serverSocket.getLocalSocketAddress()
).toHostPortString()
)
);
}
void closed() {
System.out.println("服务器已经关闭");
}
}

View File

@ -0,0 +1,34 @@
package com.mingliqiye.utils;
import java.net.ServerSocket;
/**
* 回调函数们
* @see DefTcpServerImplementation 示例
*/
public abstract class TcpServerImplementation {
/**
* 连接回调函数
* @param client 客户端
* @param id 客户端ID
* @return 是否允许连接
*/
abstract boolean connect(TcpSocketClient client, String id);
/**
* 断开连接回调函数
* @param client 客户端
* @param id 客户端ID
*/
abstract void disconnect(TcpSocketClient client, String id);
abstract void reception(
TcpSocketClient client,
BufferBytesEntity bufferBytesEntity
);
abstract void started(ServerSocket serverSocket);
abstract void closed();
}

View File

@ -0,0 +1,127 @@
package com.mingliqiye.utils;
import com.mingliqiye.network.endpoint.NetworkEndpoint;
import com.mingliqiye.network.endpoint.NetworkException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TcpSocketClient extends Thread {
private final InputStream inputStream;
private final OutputStream outputStream;
private final Socket socket;
private final TcpServerImplementation tcpServerImplementation;
private final TcpSocketServer father;
private final String id;
private final NetworkEndpoint endpoint;
private boolean closed = false;
public String getIds() {
return id;
}
public TcpSocketClient(
InputStream inputStream,
OutputStream outputStream,
Socket socket,
TcpServerImplementation tcpServerImplementation,
TcpSocketServer father,
String id
) {
this.inputStream = inputStream;
this.outputStream = outputStream;
this.socket = socket;
this.tcpServerImplementation = tcpServerImplementation;
this.father = father;
this.id = id;
this.endpoint = NetworkEndpoint.of(
(InetSocketAddress) socket.getRemoteSocketAddress()
);
}
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
BufferBytesEntity bufferBytesEntity = recv(1024);
if (bufferBytesEntity.getLen() == -1) break;
tcpServerImplementation.reception(this, bufferBytesEntity);
} catch (NetworkException e) {
break;
}
}
father.closeItem(id);
}
/**
* 发送指定字节长度
* @param bytes 字节
* @param off 位移
* @param len 长度
*/
public void send(byte[] bytes, int off, int len) {
try {
outputStream.write(bytes, off, len);
} catch (IOException e) {
throw new NetworkException(e);
}
}
/**
* 发送字节<br/>
* 注意 byte数组有多大发多大数组内空着的发送 0X00
* @param bytes 字节
*/
public void send(byte[] bytes) {
send(bytes, 0, bytes.length);
}
/**
* 读取指定大小buffer的数据
*
* @param buffer 缓存区大小
* @return BufferBytesEntity
* @see BufferBytesEntity
*/
public BufferBytesEntity recv(int buffer) {
byte[] bytes = new byte[buffer];
try {
return new BufferBytesEntity(
bytes,
inputStream.read(bytes),
buffer
);
} catch (IOException e) {
throw new NetworkException(e);
}
}
public void close() {
if (closed) {
return;
}
closed = true;
tcpServerImplementation.disconnect(this, id);
try {
inputStream.close();
} catch (IOException e) {
throw new NetworkException(e);
}
try {
outputStream.close();
} catch (IOException e) {
throw new NetworkException(e);
}
try {
socket.close();
} catch (IOException e) {
throw new NetworkException(e);
}
}
public NetworkEndpoint getEndpoint() {
return endpoint;
}
}

View File

@ -0,0 +1,100 @@
package com.mingliqiye.utils;
import com.mingliqiye.network.endpoint.NetworkEndpoint;
import com.mingliqiye.network.endpoint.NetworkException;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
/**
* tcp 服务器
*/
public class TcpSocketServer extends Thread implements AutoCloseable {
/**
* 客户端字典(线程安全的)
*/
private final Map<String, TcpSocketClient> clientMap =
new ConcurrentHashMap<>();
private ServerSocket serverSocket;
private final TcpServerImplementation tcpServerImplementation;
public TcpSocketServer(TcpServerImplementation tcpServerImplementation) {
if (tcpServerImplementation == null) {
tcpServerImplementation = new DefTcpServerImplementation();
}
this.tcpServerImplementation = tcpServerImplementation;
}
/**
* 绑定地址和端口号
*
* @param endpoint 地址和端口号
* @throws NetworkException 网络错误
*/
public void bing(NetworkEndpoint endpoint) {
try {
serverSocket = new ServerSocket();
serverSocket.bind(endpoint.toInetSocketAddress());
} catch (IOException e) {
throw new NetworkException(e);
}
}
public void run() {
tcpServerImplementation.started(serverSocket);
while (!Thread.currentThread().isInterrupted()) {
try {
String uuid = UUID.randomUUID().toString();
Socket socket = serverSocket.accept();
TcpSocketClient tcpSocketClient = new TcpSocketClient(
socket.getInputStream(),
socket.getOutputStream(),
socket,
tcpServerImplementation,
this,
uuid
);
if (!tcpServerImplementation.connect(tcpSocketClient, uuid)) {
tcpSocketClient.close();
return;
}
clientMap.put(uuid, tcpSocketClient);
tcpSocketClient.start();
} catch (InterruptedIOException e) {
Thread.currentThread().interrupt();
break;
} catch (IOException e) {
throw new NetworkException(e);
}
}
}
public void closeItem(String id) {
TcpSocketClient tcpSocketClient = clientMap.get(id);
if (tcpSocketClient == null) {
return;
}
clientMap.remove(id);
tcpSocketClient.close();
}
@Override
public void close() {
tcpServerImplementation.closed();
clientMap.forEach((k, v) -> {
v.close();
});
clientMap.clear();
this.interrupt();
try {
serverSocket.close();
} catch (IOException e) {}
}
}

View File

@ -1,27 +0,0 @@
name: Gitea Actions Build
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
on:
push:
branches:
- master
jobs:
Build:
runs-on: ubuntu-dev
steps:
- name: Check out repository code
uses: https://git.mingliqiye.com/Actions/checkout@v4
- name: build-test
run: |
source gradle.properties
gradle
gradle build-jar
- name: Releases
run: |
source gradle.properties
SHA=${{gitea.sha}}
curl -o- https://git.mingliqiye.com/Actions/com.mingliqiye.gitea.releases/raw/branch/master/install.sh | bash
FILENAME="${GROUPSID}-${VERSIONS}.jar"
java -jar com.mingliqiye.gitea.releases.jar -s "${{gitea.server_url}}" -o "${{gitea.repository_owner}}" -r ${{gitea.event.repository.name}} -t "${{gitea.token}}" -ti "Auto releases ${{gitea.sha}} ${VERSIONS}" -b "# Auto releases wtih ${{gitea.event.head_commit.message}} - [${{gitea.sha}}](${{gitea.event.head_commit.url}})" -tn "Auto-Releases-${VERSIONS}-${SHA:0:10}" -a "build/libs"